@cat-factory/integrations 0.152.7 → 0.153.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/index.d.ts +5 -2
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +5 -2
  4. package/dist/index.js.map +1 -1
  5. package/dist/modules/tasks/GitHubIssuesProvider.d.ts +9 -1
  6. package/dist/modules/tasks/GitHubIssuesProvider.d.ts.map +1 -1
  7. package/dist/modules/tasks/GitHubIssuesProvider.js +18 -0
  8. package/dist/modules/tasks/GitHubIssuesProvider.js.map +1 -1
  9. package/dist/modules/tasks/GitLabIssuesProvider.d.ts +20 -1
  10. package/dist/modules/tasks/GitLabIssuesProvider.d.ts.map +1 -1
  11. package/dist/modules/tasks/GitLabIssuesProvider.js +30 -0
  12. package/dist/modules/tasks/GitLabIssuesProvider.js.map +1 -1
  13. package/dist/modules/tasks/JiraProvider.d.ts +6 -0
  14. package/dist/modules/tasks/JiraProvider.d.ts.map +1 -1
  15. package/dist/modules/tasks/JiraProvider.js +7 -0
  16. package/dist/modules/tasks/JiraProvider.js.map +1 -1
  17. package/dist/modules/tasks/LinearTaskProvider.d.ts +6 -0
  18. package/dist/modules/tasks/LinearTaskProvider.d.ts.map +1 -1
  19. package/dist/modules/tasks/LinearTaskProvider.js +7 -0
  20. package/dist/modules/tasks/LinearTaskProvider.js.map +1 -1
  21. package/dist/modules/tasks/gitlab-issues.logic.d.ts +10 -0
  22. package/dist/modules/tasks/gitlab-issues.logic.d.ts.map +1 -1
  23. package/dist/modules/tasks/gitlab-issues.logic.js +12 -0
  24. package/dist/modules/tasks/gitlab-issues.logic.js.map +1 -1
  25. package/dist/modules/tasks/intakeMatch.logic.d.ts +6 -5
  26. package/dist/modules/tasks/intakeMatch.logic.d.ts.map +1 -1
  27. package/dist/modules/tasks/intakeMatch.logic.js +33 -14
  28. package/dist/modules/tasks/intakeMatch.logic.js.map +1 -1
  29. package/dist/modules/tasks/webhook/adapters.d.ts +16 -0
  30. package/dist/modules/tasks/webhook/adapters.d.ts.map +1 -1
  31. package/dist/modules/tasks/webhook/adapters.js +117 -1
  32. package/dist/modules/tasks/webhook/adapters.js.map +1 -1
  33. package/dist/modules/tasks/webhook/hmac.d.ts +11 -0
  34. package/dist/modules/tasks/webhook/hmac.d.ts.map +1 -1
  35. package/dist/modules/tasks/webhook/hmac.js +30 -6
  36. package/dist/modules/tasks/webhook/hmac.js.map +1 -1
  37. package/dist/modules/tasks/writeback/jira.writeback.d.ts +4 -0
  38. package/dist/modules/tasks/writeback/jira.writeback.d.ts.map +1 -0
  39. package/dist/modules/tasks/writeback/jira.writeback.js +89 -0
  40. package/dist/modules/tasks/writeback/jira.writeback.js.map +1 -0
  41. package/dist/modules/tasks/writeback/linear.writeback.d.ts +4 -0
  42. package/dist/modules/tasks/writeback/linear.writeback.d.ts.map +1 -0
  43. package/dist/modules/tasks/writeback/linear.writeback.js +66 -0
  44. package/dist/modules/tasks/writeback/linear.writeback.js.map +1 -0
  45. package/dist/modules/tasks/writeback/repo-issue.writeback.d.ts +32 -0
  46. package/dist/modules/tasks/writeback/repo-issue.writeback.d.ts.map +1 -0
  47. package/dist/modules/tasks/writeback/repo-issue.writeback.js +70 -0
  48. package/dist/modules/tasks/writeback/repo-issue.writeback.js.map +1 -0
  49. package/dist/modules/writeback/IssueWritebackService.d.ts +69 -111
  50. package/dist/modules/writeback/IssueWritebackService.d.ts.map +1 -1
  51. package/dist/modules/writeback/IssueWritebackService.js +155 -222
  52. package/dist/modules/writeback/IssueWritebackService.js.map +1 -1
  53. package/package.json +4 -4
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jira.writeback.js","sourceRoot":"","sources":["../../../../src/modules/tasks/writeback/jira.writeback.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { TaskSourceWritebackAdapter } from '@cat-factory/kernel';
2
+ /** Linear's GraphQL writeback adapter, wired on the provider itself. */
3
+ export declare const linearWriteback: TaskSourceWritebackAdapter;
4
+ //# sourceMappingURL=linear.writeback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linear.writeback.d.ts","sourceRoot":"","sources":["../../../../src/modules/tasks/writeback/linear.writeback.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAwB,MAAM,qBAAqB,CAAA;AA4B3F,wEAAwE;AACxE,eAAO,MAAM,eAAe,EAAE,0BAsB7B,CAAA"}
@@ -0,0 +1,66 @@
1
+ import { LinearGraphqlClient, linearAuthFromCredentials } from '../../shared/linear.client.js';
2
+ import { LINEAR_COMMENT_CREATE_MUTATION, LINEAR_ISSUE_ID_QUERY, LINEAR_ISSUE_RESOLVE_LOOKUP_QUERY, LINEAR_ISSUE_UPDATE_MUTATION, buildLinearCommentVariables, buildLinearStateUpdateVariables, pickStateIdByType, } from '../../tracker/linear.writeback.logic.js';
3
+ // The writeback capability of the Linear task source.
4
+ //
5
+ // Linear identifies an issue by UUID in its mutations while the stored external id is the human
6
+ // identifier (`ENG-123`), so every write is a lookup then a mutation. Resolve and claim are both
7
+ // transitions to a workflow state of a standard TYPE (`completed` / `started`), because Linear
8
+ // has no native close, which is why the resolve lookup also reads the team's states.
9
+ //
10
+ // The transport is `LinearGraphqlClient`, the same host-pinned, redirect-safe client the
11
+ // provider's reads use, rather than a caller-injected `fetch`: the writeback now rides the
12
+ // provider, so there is one auth + SSRF policy for everything this source does. Auth resolution
13
+ // goes through `linearAuthFromCredentials`, which THROWS on a bag with neither an OAuth token nor
14
+ // an API key. That is the honest answer for a workspace whose Linear connection is gone, where the
15
+ // writeback this replaced returned quietly and let the question echo record a marker for a
16
+ // comment nobody received.
17
+ /** Linear's GraphQL writeback adapter, wired on the provider itself. */
18
+ export const linearWriteback = {
19
+ // The OAuth token / API key comes from the connection's stored bag (`linearAuthFromCredentials`
20
+ // throws on one carrying neither), so an unreadable connection is fatal to every call here.
21
+ authenticates: 'stored-connection',
22
+ async comment(ctx, externalId, body) {
23
+ const client = clientFor(ctx);
24
+ const lookup = await client.query(LINEAR_ISSUE_ID_QUERY, {
25
+ id: externalId,
26
+ });
27
+ const issueId = requireIssueId(lookup?.issue?.id, externalId);
28
+ await client.query(LINEAR_COMMENT_CREATE_MUTATION, buildLinearCommentVariables(issueId, body));
29
+ },
30
+ async resolve(ctx, externalId) {
31
+ await transition(ctx, externalId, 'completed');
32
+ },
33
+ /** Linear HAS workflow states, so the intake mark is a transition and `mark.label` is unused. */
34
+ async markInProgress(ctx, externalId) {
35
+ await transition(ctx, externalId, 'started');
36
+ },
37
+ };
38
+ /**
39
+ * Move an issue to the team's workflow state of a standard type. A team whose workflow has no
40
+ * state of that type is a no-op rather than an error (there is nothing to move to), where an
41
+ * unresolvable ISSUE throws: the difference between a workflow that cannot express the step and
42
+ * an issue this connection cannot see.
43
+ */
44
+ async function transition(ctx, externalId, stateType) {
45
+ const client = clientFor(ctx);
46
+ const lookup = await client.query(LINEAR_ISSUE_RESOLVE_LOOKUP_QUERY, { id: externalId });
47
+ const issueId = requireIssueId(lookup?.issue?.id, externalId);
48
+ const stateId = pickStateIdByType(lookup?.issue?.team?.states?.nodes ?? [], stateType);
49
+ if (!stateId)
50
+ return;
51
+ await client.query(LINEAR_ISSUE_UPDATE_MUTATION, buildLinearStateUpdateVariables(issueId, stateId));
52
+ }
53
+ function clientFor(ctx) {
54
+ return new LinearGraphqlClient(linearAuthFromCredentials(ctx.credentials));
55
+ }
56
+ /**
57
+ * An identifier Linear does not resolve is a throw, not a skip: the caller is recording whether
58
+ * the comment landed, and "no such issue for this connection" is exactly the broken link a
59
+ * silent return would hide.
60
+ */
61
+ function requireIssueId(id, externalId) {
62
+ if (!id)
63
+ throw new Error(`Linear issue ${externalId} is not readable through this connection`);
64
+ return id;
65
+ }
66
+ //# sourceMappingURL=linear.writeback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linear.writeback.js","sourceRoot":"","sources":["../../../../src/modules/tasks/writeback/linear.writeback.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAA;AAC9F,OAAO,EACL,8BAA8B,EAC9B,qBAAqB,EACrB,iCAAiC,EACjC,4BAA4B,EAC5B,2BAA2B,EAC3B,+BAA+B,EAC/B,iBAAiB,GAElB,MAAM,yCAAyC,CAAA;AAEhD,sDAAsD;AACtD,EAAE;AACF,gGAAgG;AAChG,iGAAiG;AACjG,+FAA+F;AAC/F,qFAAqF;AACrF,EAAE;AACF,yFAAyF;AACzF,2FAA2F;AAC3F,gGAAgG;AAChG,kGAAkG;AAClG,mGAAmG;AACnG,2FAA2F;AAC3F,2BAA2B;AAE3B,wEAAwE;AACxE,MAAM,CAAC,MAAM,eAAe,GAA+B;IACzD,gGAAgG;IAChG,4FAA4F;IAC5F,aAAa,EAAE,mBAAmB;IAElC,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI;QACjC,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,CAAA;QAC7B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAA8B,qBAAqB,EAAE;YACpF,EAAE,EAAE,UAAU;SACf,CAAC,CAAA;QACF,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,UAAU,CAAC,CAAA;QAC7D,MAAM,MAAM,CAAC,KAAK,CAAC,8BAA8B,EAAE,2BAA2B,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAA;IAChG,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,UAAU;QAC3B,MAAM,UAAU,CAAC,GAAG,EAAE,UAAU,EAAE,WAAW,CAAC,CAAA;IAChD,CAAC;IAED,iGAAiG;IACjG,KAAK,CAAC,cAAc,CAAC,GAAG,EAAE,UAAU;QAClC,MAAM,UAAU,CAAC,GAAG,EAAE,UAAU,EAAE,SAAS,CAAC,CAAA;IAC9C,CAAC;CACF,CAAA;AAED;;;;;GAKG;AACH,KAAK,UAAU,UAAU,CACvB,GAAyB,EACzB,UAAkB,EAClB,SAAkC;IAElC,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,CAAA;IAC7B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAE9B,iCAAiC,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,CAAA;IACzD,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,UAAU,CAAC,CAAA;IAC7D,MAAM,OAAO,GAAG,iBAAiB,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,EAAE,EAAE,SAAS,CAAC,CAAA;IACtF,IAAI,CAAC,OAAO;QAAE,OAAM;IACpB,MAAM,MAAM,CAAC,KAAK,CAChB,4BAA4B,EAC5B,+BAA+B,CAAC,OAAO,EAAE,OAAO,CAAC,CAClD,CAAA;AACH,CAAC;AAED,SAAS,SAAS,CAAC,GAAyB;IAC1C,OAAO,IAAI,mBAAmB,CAAC,yBAAyB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAA;AAC5E,CAAC;AAED;;;;GAIG;AACH,SAAS,cAAc,CAAC,EAAsB,EAAE,UAAkB;IAChE,IAAI,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,gBAAgB,UAAU,0CAA0C,CAAC,CAAA;IAC9F,OAAO,EAAE,CAAA;AACX,CAAC"}
@@ -0,0 +1,32 @@
1
+ import { type GitHubClient, type GitHubInstallationRepository, type TaskSourceWritebackAdapter, type VcsProvider } from '@cat-factory/kernel';
2
+ export interface RepoIssueWritebackDependencies {
3
+ /** The client that can read the workspace's connection for this source. */
4
+ client: GitHubClient;
5
+ /** Resolves the workspace's VCS connection row. */
6
+ installations: GitHubInstallationRepository;
7
+ /** Split a stored external id into its repo + issue number, or null when it does not parse. */
8
+ parseExternalId(externalId: string): {
9
+ owner: string;
10
+ repo: string;
11
+ number: number;
12
+ } | null;
13
+ /** The provider the workspace's connection row must carry for this source to be readable. */
14
+ provider: VcsProvider;
15
+ /**
16
+ * How this vendor's issue comments are addressed:
17
+ *
18
+ * - `shared-with-pull-requests` (GitHub): issues and PRs share one number space and one comment
19
+ * API, so the client's `comment` IS the issue comment.
20
+ * - `dedicated` (GitLab): they are separate endpoints over separate `iid` spaces, so only
21
+ * `commentOnIssue` addresses an issue, and a client without it is REFUSED rather than fallen
22
+ * back from.
23
+ */
24
+ issueComments: 'shared-with-pull-requests' | 'dedicated';
25
+ /** How the source is named in a refusal an operator reads (`GitHub`, `GitLab`). */
26
+ label: string;
27
+ }
28
+ /** Build the writeback adapter for a repo-backed issue source. */
29
+ export declare function createRepoIssueWriteback(deps: RepoIssueWritebackDependencies): TaskSourceWritebackAdapter;
30
+ /** The label applied on pickup when the intake schedule names none. */
31
+ export declare const DEFAULT_IN_PROGRESS_LABEL = "in-progress";
32
+ //# sourceMappingURL=repo-issue.writeback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo-issue.writeback.d.ts","sourceRoot":"","sources":["../../../../src/modules/tasks/writeback/repo-issue.writeback.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,YAAY,EACjB,KAAK,4BAA4B,EAEjC,KAAK,0BAA0B,EAE/B,KAAK,WAAW,EACjB,MAAM,qBAAqB,CAAA;AA+B5B,MAAM,WAAW,8BAA8B;IAC7C,2EAA2E;IAC3E,MAAM,EAAE,YAAY,CAAA;IACpB,mDAAmD;IACnD,aAAa,EAAE,4BAA4B,CAAA;IAC3C,+FAA+F;IAC/F,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IAC3F,6FAA6F;IAC7F,QAAQ,EAAE,WAAW,CAAA;IACrB;;;;;;;;OAQG;IACH,aAAa,EAAE,2BAA2B,GAAG,WAAW,CAAA;IACxD,mFAAmF;IACnF,KAAK,EAAE,MAAM,CAAA;CACd;AAED,kEAAkE;AAClE,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,8BAA8B,GACnC,0BAA0B,CAkF5B;AAED,uEAAuE;AACvE,eAAO,MAAM,yBAAyB,gBAAgB,CAAA"}
@@ -0,0 +1,70 @@
1
+ import { ConflictError, UnavailableError, ValidationError, } from '@cat-factory/kernel';
2
+ /** Build the writeback adapter for a repo-backed issue source. */
3
+ export function createRepoIssueWriteback(deps) {
4
+ /**
5
+ * The workspace's connection for this source, read ONCE per batch. The memo is the context's,
6
+ * so it lives exactly as long as the fan-out that shares it: a later hook builds a fresh
7
+ * context and re-reads, which is what keeps a reconnected installation from being hidden by a
8
+ * cache with a lifetime of its own.
9
+ */
10
+ const connectionFor = (ctx) => ctx.once(`${deps.provider}.installation`, async () => {
11
+ const connection = await deps.installations.getByWorkspace(ctx.workspaceId);
12
+ if (!connection || connection.provider !== deps.provider) {
13
+ throw new ConflictError(`This workspace has no ${deps.label} connection, so its issues cannot be written back to.`);
14
+ }
15
+ return connection;
16
+ });
17
+ const target = async (ctx, externalId) => {
18
+ const id = deps.parseExternalId(externalId);
19
+ if (!id) {
20
+ throw new ValidationError(`"${externalId}" is not a valid ${deps.label} issue reference`);
21
+ }
22
+ const connection = await connectionFor(ctx);
23
+ return {
24
+ installationId: connection.installationId,
25
+ ref: { owner: id.owner, repo: id.repo },
26
+ id,
27
+ };
28
+ };
29
+ return {
30
+ // Both vendors authenticate through the workspace's VCS installation, resolved above from
31
+ // `workspaceId`. The tracker connection row carries only the inbound reply secret for them,
32
+ // so an unreadable one costs the reply channel and nothing else.
33
+ authenticates: 'out-of-band',
34
+ async comment(ctx, externalId, body) {
35
+ const { installationId, ref, id } = await target(ctx, externalId);
36
+ if (deps.issueComments === 'shared-with-pull-requests') {
37
+ await deps.client.comment(installationId, ref, id.number, body);
38
+ return;
39
+ }
40
+ const commentOnIssue = deps.client.commentOnIssue;
41
+ if (!commentOnIssue) {
42
+ // Never a silent no-op and never a fall-through to `comment`: the fall-through is the
43
+ // cross-posting bug the port doc names, and a no-op here would be recorded as delivered.
44
+ throw new UnavailableError(`This deployment's ${deps.label} client cannot comment on issues.`);
45
+ }
46
+ await commentOnIssue.call(deps.client, installationId, ref, id.number, body);
47
+ },
48
+ async resolve(ctx, externalId) {
49
+ const { installationId, ref, id } = await target(ctx, externalId);
50
+ await deps.client.closeIssue(installationId, ref, id.number);
51
+ },
52
+ /**
53
+ * Neither vendor has a workflow status on an issue, so the in-progress mark IS the label.
54
+ * A client without the label write refuses rather than commenting-without-marking: the
55
+ * pickup's whole point is claiming the issue where it was filed, and an unmarked claim reads
56
+ * to the next scan as an issue nobody took.
57
+ */
58
+ async markInProgress(ctx, externalId, mark) {
59
+ const { installationId, ref, id } = await target(ctx, externalId);
60
+ const applyLabel = deps.client.applyIssueLabel;
61
+ if (!applyLabel) {
62
+ throw new UnavailableError(`This deployment's ${deps.label} client cannot apply an issue label, so a picked-up issue cannot be marked in progress.`);
63
+ }
64
+ await applyLabel.call(deps.client, installationId, ref, id.number, mark.label ?? DEFAULT_IN_PROGRESS_LABEL);
65
+ },
66
+ };
67
+ }
68
+ /** The label applied on pickup when the intake schedule names none. */
69
+ export const DEFAULT_IN_PROGRESS_LABEL = 'in-progress';
70
+ //# sourceMappingURL=repo-issue.writeback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo-issue.writeback.js","sourceRoot":"","sources":["../../../../src/modules/tasks/writeback/repo-issue.writeback.ts"],"names":[],"mappings":"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"}
@@ -1,66 +1,39 @@
1
- import { type Logger, type Block, type Clock, type IssueWritebackProvider, type PullRequestRef, type ReviewQuestionPost, type ReviewQuestionPostOutcome, type ReviewQuestionPostRepository, type TaskConnectionStore, type TaskRepository, type TaskSourceKind, type ReviewReplyAck, type TrackerSettingsRepository } from '@cat-factory/kernel';
2
- import type { FetchLike, JiraConnection, LinearConnection } from '../tracker/TicketTrackerService.js';
1
+ import { type Logger, type Block, type Clock, type IssueWritebackProvider, type PullRequestRef, type ReviewQuestionPost, type ReviewQuestionPostOutcome, type ReviewQuestionPostRepository, type TaskConnectionStore, type TaskRepository, type TaskSourceKind, type TaskSourceProvider, type ReviewReplyAck, type TrackerSettingsRepository } from '@cat-factory/kernel';
3
2
  export interface IssueWritebackServiceDependencies {
4
3
  trackerSettingsRepository: TrackerSettingsRepository;
5
4
  taskRepository: TaskRepository;
6
5
  /**
7
- * Post a comment on a GitHub issue identified by its `owner/repo#number` external
8
- * id. The facade resolves the workspace's installation + repo ref and calls
9
- * `GitHubClient.comment`. Absent GitHub writeback passes through.
6
+ * The task sources this deployment wires, BY REFERENCE: the same array the tasks module builds
7
+ * its registry from, so a source registered once is written back to without a second wiring
8
+ * decision (and a deployment's own source gets the whole loop for free).
10
9
  *
11
- * MUST THROW when it cannot deliver an unparseable external id, or a workspace whose
12
- * installation is gone. Returning normally is the seam's promise that the comment landed. The
13
- * fire-and-forget hooks swallow the throw as they always have, but the parked-review writeback
14
- * depends on it: a facade that silently returned on an unresolved target would have its marker
15
- * recorded `posted` for a comment nobody ever received, permanently suppressing the retry that
16
- * reconnecting the installation should produce.
10
+ * Absent or empty every writeback passes through, which is the honest reading of a deployment
11
+ * with no tracker integration at all.
17
12
  */
18
- commentOnGitHubIssue?: (workspaceId: string, externalId: string, body: string) => Promise<void>;
13
+ taskSourceProviders?: readonly TaskSourceProvider[];
19
14
  /**
20
- * Close a GitHub issue (as completed) identified by its `owner/repo#number`
21
- * external id. Absent GitHub close passes through.
22
- */
23
- closeGitHubIssue?: (workspaceId: string, externalId: string) => Promise<void>;
24
- /**
25
- * Apply a label to a GitHub issue (creating the label if absent) identified by
26
- * its `owner/repo#number` external id — the intake pickup's in-progress mark
27
- * (GitHub has no native workflow status). Absent → the mark passes through.
28
- */
29
- labelGitHubIssue?: (workspaceId: string, externalId: string, label: string) => Promise<void>;
30
- /**
31
- * Resolve the workspace's Jira credentials, or null when Jira isn't configured.
32
- * Reuses the same seam as `TicketTrackerService`. Absent → Jira writeback passes through.
33
- */
34
- resolveJiraConnection?: (workspaceId: string) => Promise<JiraConnection | null>;
35
- /**
36
- * Resolve the workspace's Linear credentials, or null when Linear isn't configured.
37
- * Reuses the same seam as `TicketTrackerService`. Absent → Linear writeback passes through.
38
- */
39
- resolveLinearConnection?: (workspaceId: string) => Promise<LinearConnection | null>;
40
- /** HTTP transport for the Jira/Linear calls (each runtime exposes a global `fetch`). */
41
- fetchImpl?: FetchLike;
42
- /**
43
- * Idempotency markers for the parked-review question writeback. Absent → the writeback
44
- * passes through entirely, because posting without a marker would re-post the same
45
- * findings on every durable-driver replay (see the port doc).
46
- */
47
- reviewQuestionPostRepository?: ReviewQuestionPostRepository;
48
- /**
49
- * The per-`(workspace, source)` tracker connection, read for ONE thing here: whether an inbound
50
- * webhook secret has been minted, which is what decides if a reply typed on the ticket can ever
51
- * reach the run (`backend/docs/adr/0032-tracker-webhook-intake.md` fails closed without one).
15
+ * The per-`(workspace, source)` tracker connection, read for two things: the credential bag a
16
+ * writeback adapter authenticates with, and whether an inbound webhook secret has been minted,
17
+ * which is what decides if a reply typed on the ticket can ever reach the run
18
+ * (`backend/docs/adr/0032-tracker-webhook-intake.md` fails closed without one).
52
19
  *
53
20
  * A question comment that leads with `@cat-factory answer …` on a connection with no secret is
54
21
  * advice that silently does nothing, and it is the reporter — the one person who came in through
55
22
  * the ticket — who follows it. So the copy asks before it promises. Absent ⇒ the ticket channel
56
- * is reported UNWIRED, which is the honest reading: a facade that cannot establish the fact
57
- * cannot offer the channel.
23
+ * is reported UNWIRED and every adapter is handed an empty bag, which is the honest reading: a
24
+ * facade that cannot open a connection cannot offer the channel or authenticate as the tenant.
58
25
  *
59
26
  * Only the per-workspace half is visible from here. The other half is the facade's own
60
27
  * `trackerCommentIngestRepository`, which both runtimes wire unconditionally and the tracker
61
28
  * webhook conformance suite proves end to end.
62
29
  */
63
30
  taskConnectionStore?: TaskConnectionStore;
31
+ /**
32
+ * Idempotency markers for the parked-review question writeback. Absent → the writeback
33
+ * passes through entirely, because posting without a marker would re-post the same
34
+ * findings on every durable-driver replay (see the port doc).
35
+ */
36
+ reviewQuestionPostRepository?: ReviewQuestionPostRepository;
64
37
  /**
65
38
  * Wall clock for the marker rows and their abandonment window. The facade's shared `Clock`,
66
39
  * like every other service here; defaults to the real clock so a test can pin time without
@@ -68,16 +41,16 @@ export interface IssueWritebackServiceDependencies {
68
41
  */
69
42
  clock?: Clock;
70
43
  /**
71
- * Where the two swallowed paths below report: a marker that could not be settled, and a
72
- * per-issue writeback that threw inside the fan-out. Absent ⇒ `noopLogger`.
44
+ * Where every degraded path reports: an unwired source, an unreadable connection, a marker that
45
+ * could not be settled, a per-issue writeback that threw inside the fan-out. Absent ⇒
46
+ * `noopLogger`.
73
47
  */
74
48
  logger?: Logger;
75
49
  }
76
- /** The GitHub in-progress label applied on pickup when the schedule doesn't name one. */
77
- export declare const DEFAULT_IN_PROGRESS_LABEL = "in-progress";
78
50
  export declare class IssueWritebackService implements IssueWritebackProvider {
79
51
  private readonly deps;
80
52
  private readonly log;
53
+ private readonly sources;
81
54
  constructor(deps: IssueWritebackServiceDependencies);
82
55
  onPullRequestOpened(workspaceId: string, block: Block, pr: PullRequestRef): Promise<void>;
83
56
  onPullRequestMerged(workspaceId: string, block: Block, pr: PullRequestRef): Promise<void>;
@@ -86,24 +59,6 @@ export declare class IssueWritebackService implements IssueWritebackProvider {
86
59
  inProgressLabel?: string;
87
60
  }): Promise<void>;
88
61
  postReviewQuestions(workspaceId: string, block: Block, post: ReviewQuestionPost): Promise<ReviewQuestionPostOutcome>;
89
- /**
90
- * Whether a reply typed on a ticket reaches the run, per DISTINCT source across the block's
91
- * linked issues.
92
- *
93
- * One connection read per distinct source, indexed into a `Map`, rather than one per issue: the
94
- * fact belongs to `(workspace, source)`, and a block linked to three issues on one tracker would
95
- * otherwise pay three decrypting reads for one answer.
96
- *
97
- * An unreadable connection resolves to `false` and is REPORTED, never guessed at: the failure
98
- * mode of guessing `true` is a reporter told to reply where nothing listens, which is the exact
99
- * thing this resolution exists to prevent.
100
- *
101
- * Unreadable is scoped to the SOURCE that was unreadable. The block's issues can span trackers,
102
- * and a corrupt Linear envelope is no evidence at all about the workspace's Jira connection —
103
- * so a batch-wide catch would take a working reply channel away from a healthy ticket and tell
104
- * its reporter to use the API path instead.
105
- */
106
- private resolveTicketReplyChannels;
107
62
  /**
108
63
  * Acknowledge a ticket reply on the very issue it arrived on.
109
64
  *
@@ -120,6 +75,39 @@ export declare class IssueWritebackService implements IssueWritebackProvider {
120
75
  source: TaskSourceKind;
121
76
  externalId: string;
122
77
  }, ack: ReviewReplyAck): Promise<void>;
78
+ /**
79
+ * What this deployment can do for each source the given issues sit on: the registered
80
+ * provider's writeback adapter, the batch context carrying the workspace's credential bag for
81
+ * it, and whether a reply typed on one of its tickets reaches the run.
82
+ *
83
+ * ONE connection read for the whole set, indexed by source.
84
+ *
85
+ * What an unreadable row costs is the ADAPTER's own declaration (`authenticates`), never a guess
86
+ * from the empty bag it leaves behind. A `stored-connection` adapter resolves to `unreadable`
87
+ * and is REPORTED: writing back with a bag that would not open authenticates as nobody, and the
88
+ * vendor's rejection would name the wrong fault. An `out-of-band` adapter (GitHub Issues rides
89
+ * the workspace's App, GitLab Issues its VCS connection) never needed the row to post, so it
90
+ * stays READY and loses only what the row actually carried: the reply channel, which is
91
+ * WITHHELD rather than assumed, because telling a reporter to reply where nothing listens is
92
+ * the exact thing this resolution exists to prevent.
93
+ *
94
+ * Both verdicts are scoped to the SOURCE they were learned about. A block's issues can span
95
+ * trackers, and a corrupt Linear envelope is no evidence at all about the workspace's Jira
96
+ * connection, so a batch-wide failure would take a working channel away from a healthy ticket.
97
+ */
98
+ private resolveSources;
99
+ /**
100
+ * Record a connection that would not open, costing each source only what it actually costs.
101
+ *
102
+ * An adapter that authenticates WITH the bag is lost until the connection is repaired, so it
103
+ * resolves to `unreadable` and every call for it fails loudly. An `out-of-band` one keeps its
104
+ * whole writeback (it authenticates from `workspaceId` and only ever read this row for the
105
+ * inbound secret) and loses just the reply channel, which the seeded entry already withholds.
106
+ * Reading the failure as one fact for every source is what would let a rotated
107
+ * `TASKS_ENCRYPTION_KEY` silence GitHub's PR notices, and the two log lines say which happened
108
+ * because an operator acts on them differently.
109
+ */
110
+ private markUnreadable;
123
111
  /**
124
112
  * Run a writeback per issue, isolating failures so one bad issue can't block the rest. Each
125
113
  * isolated failure names the issue it belongs to: these hooks are fire-and-forget, so a
@@ -128,52 +116,22 @@ export declare class IssueWritebackService implements IssueWritebackProvider {
128
116
  */
129
117
  private forEachIssue;
130
118
  /**
131
- * Post a comment on one linked issue. Returns whether this deployment has a transport for that
132
- * issue's source at all; a wired transport that cannot deliver THROWS (see the seam docs), so
133
- * `true` means the comment landed. The fire-and-forget hooks ignore both signals, but the
134
- * parked-review writeback distinguishes them: an unwired source is a permanent no-op to retry
135
- * once someone wires it, a throw is a failure to retry on the next replay, and neither may be
136
- * recorded as `posted`.
119
+ * Post a comment on one linked issue. Returns whether this deployment has a writeback for that
120
+ * issue's source at all; an adapter that cannot deliver THROWS (see the port), so `true` means
121
+ * the comment landed. The fire-and-forget hooks ignore both signals, but the parked-review
122
+ * writeback distinguishes them: an unwired source is a permanent no-op to retry once someone
123
+ * wires it, a throw is a failure to retry on the next replay, and neither may be recorded as
124
+ * `posted`.
137
125
  */
138
126
  private comment;
139
- private resolve;
140
127
  /**
141
- * Mark a picked-up issue in-progress: the vendor's in-progress workflow
142
- * transition (Jira's `indeterminate` status category / Linear's `started`
143
- * state), or the in-progress label for GitHub, which has no native status.
144
- */
145
- private markInProgress;
146
- /**
147
- * Comment on a Linear issue: resolve its UUID by identifier, then `commentCreate`.
148
- * On merge this runs before {@link resolveLinear}, so the issue is looked up twice
149
- * (here for the UUID, there for the UUID + the team's workflow states). That second
150
- * lookup is unavoidable — only it carries the states needed to pick the resolved
151
- * state — and the duplicated read is one cheap `issue(id:){id}` call, so the seam is
152
- * kept uniform with the GitHub/Jira comment/resolve split rather than special-cased.
153
- */
154
- private commentLinear;
155
- /**
156
- * Transition a Linear issue: look up its UUID + team states, pick the target
157
- * state (`completed` on resolve, `started` on pickup), then `issueUpdate`.
158
- */
159
- private transitionLinear;
160
- /**
161
- * Issue a Linear GraphQL request for the workspace's connection. Returns the
162
- * validated `data` (or null when Linear isn't configured). Throws on a GraphQL /
163
- * HTTP error so the per-issue isolation in {@link forEachIssue} reports and swallows it.
164
- */
165
- private linearRequest;
166
- /**
167
- * Transition a Jira issue into a standard status category: `done` on resolve,
168
- * `indeterminate` (In Progress) on pickup. Lists the issue's available
169
- * transitions and fires the first one landing in the category.
170
- */
171
- private transitionJira;
172
- /**
173
- * Issue a Jira REST v3 request for the workspace's connection. Returns the parsed
174
- * JSON body (or null on an empty/204 response). Throws on a non-OK status so the
175
- * per-issue isolation in {@link forEachIssue} reports and swallows it.
128
+ * Apply the issue's state change for a hook: `resolve` on merge, `markInProgress` on pickup.
129
+ *
130
+ * Both are OPTIONAL on the adapter, and an omitted one is reported rather than passed over in
131
+ * silence. A tracker whose vendor has no such notion is a real answer an operator may need (the
132
+ * merge comment landed and the issue stayed open, and only this line says why), and it must not
133
+ * read like the write simply succeeded.
176
134
  */
177
- private jiraRequest;
135
+ private applyState;
178
136
  }
179
137
  //# sourceMappingURL=IssueWritebackService.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"IssueWritebackService.d.ts","sourceRoot":"","sources":["../../../src/modules/writeback/IssueWritebackService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"IssueWritebackService.d.ts","sourceRoot":"","sources":["../../../src/modules/writeback/IssueWritebackService.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,MAAM,EAOX,KAAK,KAAK,EACV,KAAK,KAAK,EACV,KAAK,sBAAsB,EAC3B,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,4BAA4B,EACjC,KAAK,mBAAmB,EAGxB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EAGvB,KAAK,cAAc,EACnB,KAAK,yBAAyB,EAE/B,MAAM,qBAAqB,CAAA;AAwB5B,MAAM,WAAW,iCAAiC;IAChD,yBAAyB,EAAE,yBAAyB,CAAA;IACpD,cAAc,EAAE,cAAc,CAAA;IAC9B;;;;;;;OAOG;IACH,mBAAmB,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAA;IACnD;;;;;;;;;;;;;;;OAeG;IACH,mBAAmB,CAAC,EAAE,mBAAmB,CAAA;IACzC;;;;OAIG;IACH,4BAA4B,CAAC,EAAE,4BAA4B,CAAA;IAC3D;;;;OAIG;IACH,KAAK,CAAC,EAAE,KAAK,CAAA;IACb;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAyBD,qBAAa,qBAAsB,YAAW,sBAAsB;IAItD,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHjC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;IAC5B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuB;IAE/C,YAA6B,IAAI,EAAE,iCAAiC,EAGnE;IAEK,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAkB9F;IAEK,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAmB9F;IAEK,eAAe,CACnB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,eAAe,CAAC,EAAE,MAAM,CAAA;KAAE,GAClD,OAAO,CAAC,IAAI,CAAC,CAwBf;IAEK,mBAAmB,CACvB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,yBAAyB,CAAC,CAyHpC;IAED;;;;;;;;;;;OAWG;IACG,kBAAkB,CACtB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE;QAAE,MAAM,EAAE,cAAc,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,EACrD,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,IAAI,CAAC,CAGf;IAED;;;;;;;;;;;;;;;;;;;OAmBG;YACW,cAAc;IAyD5B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,cAAc;IAkBtB;;;;;OAKG;YACW,YAAY;IAgB1B;;;;;;;OAOG;YACW,OAAO;IA4BrB;;;;;;;OAOG;YACW,UAAU;CAkCzB"}