@shipfox/api-integration-sentry 10.2.0 → 12.0.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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shipfox/api-integration-sentry",
3
3
  "license": "MIT",
4
- "version": "10.2.0",
4
+ "version": "12.0.0",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/ShipfoxHQ/shipfox.git",
@@ -22,15 +22,15 @@
22
22
  "drizzle-orm": "^0.45.2",
23
23
  "ky": "^2.0.0",
24
24
  "zod": "^4.4.3",
25
- "@shipfox/api-auth-context": "10.2.0",
26
- "@shipfox/api-integration-spi": "0.2.2",
27
- "@shipfox/api-integration-sentry-dto": "9.0.2",
25
+ "@shipfox/api-auth-context": "12.0.0",
26
+ "@shipfox/api-integration-spi": "1.0.0",
27
+ "@shipfox/api-integration-sentry-dto": "12.0.0",
28
28
  "@shipfox/config": "1.2.4",
29
- "@shipfox/node-drizzle": "0.3.4",
30
- "@shipfox/node-fastify": "0.4.0",
31
- "@shipfox/node-module": "1.0.4",
29
+ "@shipfox/node-drizzle": "0.3.5",
30
+ "@shipfox/node-fastify": "0.4.1",
31
+ "@shipfox/node-module": "1.0.5",
32
32
  "@shipfox/node-opentelemetry": "0.6.3",
33
- "@shipfox/node-postgres": "0.4.4"
33
+ "@shipfox/node-postgres": "0.5.0"
34
34
  },
35
35
  "imports": {
36
36
  "#*": "./dist/*"
package/src/api/client.ts CHANGED
@@ -103,7 +103,7 @@ export function createSentryApiClient(): SentryApiClient {
103
103
 
104
104
  // The typed error deliberately drops Sentry's status and body so no token, code,
105
105
  // or client secret can leak to the client or the logged error chain. That also
106
- // strips the one detail a self-hoster needs to fix a misconfigured Sentry app
106
+ // strips the one detail a self-hoster needs to fix a misconfigured Sentry app.
107
107
  // e.g. a 403 on `get-installation` means the app is missing "Organization: Read"
108
108
  // (see README "Required permissions"). So we log the upstream status
109
109
  // here, the only place it survives, keyed by the operation that failed.
@@ -41,7 +41,7 @@ export class SentryVerificationInProgressError extends Error {
41
41
  /**
42
42
  * Base for issue deliveries we received and authenticated but deliberately do
43
43
  * not publish. The webhook layer records them for dedup and acknowledges with a
44
- * 204 rather than treating them as failures a sustained non-2xx can make Sentry
44
+ * 204 rather than treating them as failures: a sustained non-2xx can make Sentry
45
45
  * disable the webhook. Carries no HTTP concerns so workers/jobs can reuse it.
46
46
  */
47
47
  export class SentryIssueDroppedError extends Error {}
@@ -121,7 +121,7 @@ function run(options: RunOptions = {}) {
121
121
  };
122
122
  }
123
123
 
124
- describe('handleSentryConnect browser-first (no row)', () => {
124
+ describe('handleSentryConnect: browser-first (no row)', () => {
125
125
  it('exchanges, persists the unclaimed row, then binds and verifies last', async () => {
126
126
  const sentry = sentryClient();
127
127
  const {connectSentryInstallation, persistVerifiedUnclaimedInstallation, result} = run({sentry});
@@ -179,7 +179,7 @@ describe('handleSentryConnect — browser-first (no row)', () => {
179
179
  });
180
180
  });
181
181
 
182
- describe('handleSentryConnect verified, unclaimed row exists (webhook-first)', () => {
182
+ describe('handleSentryConnect: verified, unclaimed row exists (webhook-first)', () => {
183
183
  it('binds via same-code race when the exchange is already used and the hash matches', async () => {
184
184
  const sentry = sentryClient({
185
185
  exchangeAuthorizationCode: vi.fn(() =>
@@ -237,7 +237,7 @@ describe('handleSentryConnect — verified, unclaimed row exists (webhook-first)
237
237
  });
238
238
  });
239
239
 
240
- describe('handleSentryConnect already claimed / tombstoned', () => {
240
+ describe('handleSentryConnect: already claimed / tombstoned', () => {
241
241
  it('is idempotent for an install already claimed to the same workspace', async () => {
242
242
  const existing = connection({workspaceId: WORKSPACE_ID});
243
243
  const {sentry, connectSentryInstallation, result} = run({
@@ -272,7 +272,7 @@ describe('handleSentryConnect — already claimed / tombstoned', () => {
272
272
  });
273
273
  });
274
274
 
275
- describe('handleSentryConnect simultaneous race', () => {
275
+ describe('handleSentryConnect: simultaneous race', () => {
276
276
  it('returns a retryable error when the code is already used and no row is visible yet', async () => {
277
277
  const sentry = sentryClient({
278
278
  exchangeAuthorizationCode: vi.fn(() =>
@@ -236,7 +236,7 @@ async function claimBrowserFirst(
236
236
  }
237
237
 
238
238
  // The browser-first exchange got "already used" with no row visible at lookup: a
239
- // concurrent webhook won the exchange. Re-read once if its verified row is now
239
+ // concurrent webhook won the exchange. Re-read once: if its verified row is now
240
240
  // visible we reconcile through the same proof rules; if it got claimed we resolve
241
241
  // it; if it was tombstoned we surface that terminally (matching the top-level
242
242
  // check); otherwise it is still mid-flight, so the claim is retryable.
@@ -94,7 +94,7 @@ async function createTestApp(options: CreateTestAppOptions = {}): Promise<Fastif
94
94
  updatedAt: new Date(),
95
95
  }),
96
96
  ),
97
- // Webhook receiver dependencies install/connect tests don't exercise them.
97
+ // Webhook receiver dependencies: install/connect tests don't exercise them.
98
98
  coreDb: vi.fn() as never,
99
99
  publishIntegrationEventReceived: vi.fn(() => Promise.resolve({published: false})),
100
100
  recordDeliveryOnly: vi.fn(() => Promise.resolve()),
@@ -109,7 +109,7 @@ async function createTestApp(options: CreateTestAppOptions = {}): Promise<Fastif
109
109
  function connectPayload(options: {authorize?: boolean} = {}) {
110
110
  const workspaceId = crypto.randomUUID();
111
111
  if (options.authorize !== false) {
112
- authenticatedMemberships = [{workspaceId, role: 'admin'}];
112
+ authenticatedMemberships = [{workspaceId, role: 'admin', workspaceStatus: 'active'}];
113
113
  }
114
114
  return {
115
115
  workspace_id: workspaceId,
@@ -143,7 +143,7 @@ describe('Sentry integration routes', () => {
143
143
  it('returns the external-install URL for a member', async () => {
144
144
  const app = await createTestApp();
145
145
  const workspaceId = crypto.randomUUID();
146
- authenticatedMemberships = [{workspaceId, role: 'admin'}];
146
+ authenticatedMemberships = [{workspaceId, role: 'admin', workspaceStatus: 'active'}];
147
147
 
148
148
  const res = await app.inject({
149
149
  method: 'POST',
@@ -4,7 +4,7 @@ import {Factory} from 'fishery';
4
4
  // over the wire: the lifecycle data nests under `data.installation` and carries
5
5
  // the single-use authorization `code`. Tests serialize the built object to form a
6
6
  // signed request body; the route parses and validates it with the production Zod
7
- // schema. Build-only the payload is never persisted, so there is no onCreate
7
+ // schema. Build-only: the payload is never persisted, so there is no onCreate
8
8
  // handler.
9
9
  export interface SentryInstallationWebhookPayload {
10
10
  action: string;
@@ -2,7 +2,7 @@ import {Factory} from 'fishery';
2
2
 
3
3
  // Raw Sentry issue webhook payload, shaped exactly as Sentry delivers it over
4
4
  // the wire. Tests serialize the built object to form a signed request body; the
5
- // route parses and validates it with the production Zod schema. Build-only the
5
+ // route parses and validates it with the production Zod schema. Build-only: the
6
6
  // payload is never persisted, so there is no onCreate handler.
7
7
  export interface SentryIssueWebhookPayload {
8
8
  action: string;