{"_id":"@bernierllc/slack-list-bridge","_rev":"5-7b89f07f6a94e0b54712cb72e565a121","name":"@bernierllc/slack-list-bridge","dist-tags":{"latest":"0.5.0"},"versions":{"0.0.1":{"name":"@bernierllc/slack-list-bridge","version":"0.0.1","keywords":["oidc","trusted-publishing","setup"],"_id":"@bernierllc/slack-list-bridge@0.0.1","maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"dist":{"shasum":"9d2eb03c3a44bb37abe409192e3babbcffa167a0","tarball":"https://registry.npmjs.org/@bernierllc/slack-list-bridge/-/slack-list-bridge-0.0.1.tgz","fileCount":2,"integrity":"sha512-o8gfVSIaHbgGtCHSjUj7b1m54XfnOTDyHJA1wGRdzW6BR8uDu0H29j3JPyTWFJvFRZgHKA5rz50mnXRy6bcpVw==","signatures":[{"sig":"MEUCIC/rM/vJLAT3p+iULSsIHFly9EgjGyUc63U7sNIvYxP+AiEA1lMxFlsGw35muhwQN0zL3g9taz0xcERxv5cJWdJUxOw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2079},"_npmUser":{"name":"mkbernier","email":"mkbernier@gmail.com"},"_npmVersion":"11.6.2","description":"OIDC trusted publishing setup package for @bernierllc/slack-list-bridge","directories":{},"_nodeVersion":"25.2.1","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/slack-list-bridge_0.0.1_1766454186215_0.6053148139654021","host":"s3://npm-registry-packages-npm-production"}},"0.3.1":{"name":"@bernierllc/slack-list-bridge","version":"0.3.1","keywords":["slack","webhook","bridge","list","workflow-builder","integration"],"author":{"name":"Bernier LLC"},"license":"UNLICENSED","_id":"@bernierllc/slack-list-bridge@0.3.1","maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"homepage":"https://github.com/bernierllc/tools#readme","bugs":{"url":"https://github.com/bernierllc/tools/issues"},"dist":{"shasum":"1cbff69ac0079d72ec502d2b751efe8537a11192","tarball":"https://registry.npmjs.org/@bernierllc/slack-list-bridge/-/slack-list-bridge-0.3.1.tgz","fileCount":42,"integrity":"sha512-NS2IVH7qMdNSANXCa5nB8m43cKwgylqpe3r4Mg6HBixHK+tvJg5FcwRIAMELVgWlT/Bs9NBCdkp8VRXqfAO4lw==","signatures":[{"sig":"MEYCIQC7G12FvqIrT+oF7LkN5rCXq2J+9TTlb63W75gohce+CgIhAMhKnE9FP4tbLAhnnmB2oI0KUtrhwKYGCwvRfkWYE0uA","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":82552},"main":"dist/index.js","_from":"file:bernierllc-slack-list-bridge-0.3.1.tgz","types":"dist/index.d.ts","scripts":{"lint":"eslint src --ext .ts","test":"jest","build":"tsc","clean":"rm -rf dist","test:run":"jest --runInBand --no-cache","test:coverage":"jest --coverage --runInBand --no-cache"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:97f4c13b-c4a9-44de-aa86-3f3e6a350ac5"}},"_resolved":"/tmp/788334610750b7d93ffa46751981721f/bernierllc-slack-list-bridge-0.3.1.tgz","_integrity":"sha512-NS2IVH7qMdNSANXCa5nB8m43cKwgylqpe3r4Mg6HBixHK+tvJg5FcwRIAMELVgWlT/Bs9NBCdkp8VRXqfAO4lw==","repository":{"url":"git+https://github.com/bernierllc/tools.git","type":"git","directory":"packages/integration/slack-list-bridge"},"_npmVersion":"11.11.0","description":"Bridge between Slack list events and arbitrary handlers with signature verification","directories":{},"_nodeVersion":"20.20.0","dependencies":{"zod":"^3.22.0","express":"^4.18.2","@slack/web-api":"^6.9.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.5.0","eslint":"^8.40.0","ts-jest":"^29.0.5","typescript":"^5.0.0","@types/node":"^18.15.0","@types/express":"^4.17.17","@typescript-eslint/parser":"^6.0.0","@typescript-eslint/eslint-plugin":"^6.0.0"},"_npmOperationalInternal":{"tmp":"tmp/slack-list-bridge_0.3.1_1773078100408_0.37487689609364105","host":"s3://npm-registry-packages-npm-production"}},"0.3.2":{"name":"@bernierllc/slack-list-bridge","version":"0.3.2","keywords":["slack","webhook","bridge","list","workflow-builder","integration"],"author":{"name":"Bernier LLC"},"license":"UNLICENSED","_id":"@bernierllc/slack-list-bridge@0.3.2","maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"homepage":"https://github.com/bernierllc/tools#readme","bugs":{"url":"https://github.com/bernierllc/tools/issues"},"dist":{"shasum":"55158428912cf35098a01dbe486588fc4f144e24","tarball":"https://registry.npmjs.org/@bernierllc/slack-list-bridge/-/slack-list-bridge-0.3.2.tgz","fileCount":42,"integrity":"sha512-28cGHbsQgBk/TB33XvCbmU3k1mW6QaJf95RKLuaS1zC3WD6U6Mut00RD2MlBQ+OFvbJq8QrprGcFpb//WDcSGw==","signatures":[{"sig":"MEQCIBA/6579AgZrSeTUC/ohAU9X69LY9cuMBJBly0M0rJXWAiAGOhzHIGhW6KH8Xox26hGB4qNo0N2cR5EZCeVNLajR0w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":82552},"main":"dist/index.js","_from":"file:bernierllc-slack-list-bridge-0.3.2.tgz","types":"dist/index.d.ts","scripts":{"lint":"eslint src --ext .ts","test":"jest","build":"tsc","clean":"rm -rf dist","test:run":"jest --runInBand --no-cache","test:coverage":"jest --coverage --runInBand --no-cache"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:97f4c13b-c4a9-44de-aa86-3f3e6a350ac5"}},"_resolved":"/home/runner/work/tools/tools/packages/integration/slack-list-bridge/bernierllc-slack-list-bridge-0.3.2.tgz","_integrity":"sha512-28cGHbsQgBk/TB33XvCbmU3k1mW6QaJf95RKLuaS1zC3WD6U6Mut00RD2MlBQ+OFvbJq8QrprGcFpb//WDcSGw==","repository":{"url":"git+https://github.com/bernierllc/tools.git","type":"git","directory":"packages/integration/slack-list-bridge"},"_npmVersion":"11.11.0","description":"Bridge between Slack list events and arbitrary handlers with signature verification","directories":{},"_nodeVersion":"20.20.0","dependencies":{"zod":"^3.22.0","express":"^4.18.2","@slack/web-api":"^6.9.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.5.0","eslint":"^8.40.0","ts-jest":"^29.0.5","typescript":"^5.0.0","@types/node":"^18.15.0","@types/express":"^4.17.17","@typescript-eslint/parser":"^6.0.0","@typescript-eslint/eslint-plugin":"^6.0.0"},"_npmOperationalInternal":{"tmp":"tmp/slack-list-bridge_0.3.2_1773163387934_0.22621204125166616","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@bernierllc/slack-list-bridge","version":"0.4.0","keywords":["slack","webhook","bridge","list","workflow-builder","integration"],"author":{"name":"Bernier LLC"},"license":"UNLICENSED","_id":"@bernierllc/slack-list-bridge@0.4.0","maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"homepage":"https://github.com/bernierllc/tools#readme","bugs":{"url":"https://github.com/bernierllc/tools/issues"},"dist":{"shasum":"433403291ba8f84646f3e971622559ba27d90018","tarball":"https://registry.npmjs.org/@bernierllc/slack-list-bridge/-/slack-list-bridge-0.4.0.tgz","fileCount":42,"integrity":"sha512-xL0ETzoScvVQd1B6sP8FhkQezv5lsNqyYkR/1OwKyldTDyYVyJrSDN1GsPEyNK/MfDxLHg9DE/Ji/jZ6cF+ajw==","signatures":[{"sig":"MEQCIGp8CuYArTc8TwH9y1QAHmd5xc8Cr1dbcmXVPEdm52n7AiBz492BU0W1vXS8sguCqN2+M1Y72yMKkWX11+WIJfKinA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":82552},"main":"dist/index.js","_from":"file:bernierllc-slack-list-bridge-0.4.0.tgz","types":"dist/index.d.ts","scripts":{"lint":"eslint src --ext .ts","test":"jest","build":"tsc","clean":"rm -rf dist","test:run":"jest --runInBand --no-cache","test:coverage":"jest --coverage --runInBand --no-cache"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:97f4c13b-c4a9-44de-aa86-3f3e6a350ac5"}},"_resolved":"/home/runner/work/tools/tools/packages/integration/slack-list-bridge/bernierllc-slack-list-bridge-0.4.0.tgz","_integrity":"sha512-xL0ETzoScvVQd1B6sP8FhkQezv5lsNqyYkR/1OwKyldTDyYVyJrSDN1GsPEyNK/MfDxLHg9DE/Ji/jZ6cF+ajw==","repository":{"url":"git+https://github.com/bernierllc/tools.git","type":"git","directory":"packages/integration/slack-list-bridge"},"_npmVersion":"11.14.1","description":"Bridge between Slack list events and arbitrary handlers with signature verification","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^3.22.0","express":"^4.18.2","@slack/web-api":"^6.9.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.5.0","eslint":"^8.40.0","ts-jest":"^29.0.5","typescript":"^5.0.0","@types/node":"^18.15.0","@types/express":"^4.17.17","@typescript-eslint/parser":"^6.0.0","@typescript-eslint/eslint-plugin":"^6.0.0"},"_npmOperationalInternal":{"tmp":"tmp/slack-list-bridge_0.4.0_1779241518173_0.9673932544212702","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"@bernierllc/slack-list-bridge","version":"0.5.0","description":"Bridge between Slack list events and arbitrary handlers with signature verification","main":"dist/index.js","types":"dist/index.d.ts","keywords":["slack","webhook","bridge","list","workflow-builder","integration"],"author":{"name":"Bernier LLC"},"license":"UNLICENSED","repository":{"type":"git","url":"git+https://github.com/bernierllc/tools.git","directory":"packages/integration/slack-list-bridge"},"dependencies":{"@slack/web-api":"^6.9.0","express":"^4.18.2","zod":"^3.22.0"},"devDependencies":{"@types/express":"^4.17.17","@types/node":"^18.15.0","@typescript-eslint/eslint-plugin":"^6.0.0","@typescript-eslint/parser":"^6.0.0","eslint":"^8.40.0","jest":"^29.5.0","ts-jest":"^29.0.5","typescript":"^5.0.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"scripts":{"build":"tsc","test":"jest","test:run":"jest --runInBand --no-cache","test:coverage":"jest --coverage --runInBand --no-cache","lint":"eslint src --ext .ts","clean":"rm -rf dist"},"_id":"@bernierllc/slack-list-bridge@0.5.0","bugs":{"url":"https://github.com/bernierllc/tools/issues"},"homepage":"https://github.com/bernierllc/tools#readme","_integrity":"sha512-NkZQxk5CuU4irkfrsr3PiRwTbcULGL+81m8HYDF/demZKV+s/MjeZYvDF0BRsKd5G7NkYSiiRI0HCdCZus5qPw==","_resolved":"/home/runner/work/tools/tools/packages/integration/slack-list-bridge/bernierllc-slack-list-bridge-0.5.0.tgz","_from":"file:bernierllc-slack-list-bridge-0.5.0.tgz","_nodeVersion":"20.20.2","_npmVersion":"11.14.1","dist":{"integrity":"sha512-NkZQxk5CuU4irkfrsr3PiRwTbcULGL+81m8HYDF/demZKV+s/MjeZYvDF0BRsKd5G7NkYSiiRI0HCdCZus5qPw==","shasum":"d28dcbc3af2aace9fdbbb6ae38aad810e80f9470","tarball":"https://registry.npmjs.org/@bernierllc/slack-list-bridge/-/slack-list-bridge-0.5.0.tgz","fileCount":42,"unpackedSize":82552,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQD7PmXsrThMsfl24T6jfChYT1Fx8xv6taZsiJNd2g5eiQIgPw/DSXB0QyjwC/GlJD47oErXn2ZNTgQPsiKu6tMiXyM="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:97f4c13b-c4a9-44de-aa86-3f3e6a350ac5"}},"directories":{},"maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/slack-list-bridge_0.5.0_1779250264490_0.9453919734863299"},"_hasShrinkwrap":false}},"time":{"created":"2025-12-23T01:43:06.093Z","modified":"2026-05-20T04:11:04.777Z","0.0.1":"2025-12-23T01:43:06.351Z","0.3.1":"2026-03-09T17:41:40.537Z","0.3.2":"2026-03-10T17:23:08.080Z","0.4.0":"2026-05-20T01:45:18.377Z","0.5.0":"2026-05-20T04:11:04.643Z"},"bugs":{"url":"https://github.com/bernierllc/tools/issues"},"author":{"name":"Bernier LLC"},"license":"UNLICENSED","homepage":"https://github.com/bernierllc/tools#readme","keywords":["slack","webhook","bridge","list","workflow-builder","integration"],"repository":{"type":"git","url":"git+https://github.com/bernierllc/tools.git","directory":"packages/integration/slack-list-bridge"},"description":"Bridge between Slack list events and arbitrary handlers with signature verification","maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"readme":"# @bernierllc/slack-list-bridge\n\nBridge between Slack list events (via Workflow Builder webhooks) and arbitrary handlers. Receives POST requests from Slack, validates signatures, parses payloads, and calls registered handlers.\n\n## Features\n\n- HTTP endpoint for Slack webhooks (Express-based)\n- Slack signature verification using signing secret\n- Payload parsing with Zod schemas for type safety\n- Type-safe event objects\n- Helper functions to update Slack list items\n- Comprehensive error handling\n\n## Installation\n\n```bash\nnpm install @bernierllc/slack-list-bridge\n```\n\n## Usage\n\n### Basic Example\n\n```typescript\nimport { createSlackListBridge } from '@bernierllc/slack-list-bridge';\nimport { WebClient } from '@slack/web-api';\n\nconst bridge = createSlackListBridge({\n  signingSecret: process.env.SLACK_SIGNING_SECRET!,\n  botToken: process.env.SLACK_BOT_TOKEN!,\n  port: 3000,\n  path: '/slack/list-webhook',\n  async handler(event) {\n    console.log('Received list event:', event);\n\n    // Access event properties\n    console.log('List ID:', event.listId);\n    console.log('Item ID:', event.itemId);\n    console.log('Title:', event.title);\n    console.log('Fields:', event.fields);\n    console.log('Created by:', event.createdBy);\n  },\n});\n\n// Later, when shutting down\nawait bridge.stop();\n```\n\n### Using Helper Functions\n\n```typescript\nimport {\n  createSlackListBridge,\n  updateSlackListItem,\n  addSlackListComment,\n  completeSlackListItem,\n} from '@bernierllc/slack-list-bridge';\nimport { WebClient } from '@slack/web-api';\n\nconst client = new WebClient(process.env.SLACK_BOT_TOKEN!);\n\nconst bridge = createSlackListBridge({\n  signingSecret: process.env.SLACK_SIGNING_SECRET!,\n  botToken: process.env.SLACK_BOT_TOKEN!,\n  async handler(event) {\n    try {\n      // Update item fields\n      await updateSlackListItem(client, event.listId, event.itemId, {\n        status: 'processing',\n        processed_at: new Date().toISOString(),\n      });\n\n      // Add a comment\n      await addSlackListComment(\n        client,\n        event.listId,\n        event.itemId,\n        'Processing started!'\n      );\n\n      // Perform your business logic here\n      await processItem(event);\n\n      // Complete the item\n      await completeSlackListItem(client, event.listId, event.itemId);\n\n      // Add completion comment\n      await addSlackListComment(\n        client,\n        event.listId,\n        event.itemId,\n        'Processing completed successfully!'\n      );\n    } catch (error) {\n      console.error('Error processing item:', error);\n      await addSlackListComment(\n        client,\n        event.listId,\n        event.itemId,\n        `Error: ${error.message}`\n      );\n    }\n  },\n});\n\nasync function processItem(event: SlackListEvent) {\n  // Your business logic here\n}\n```\n\n### Custom Port and Path\n\n```typescript\nconst bridge = createSlackListBridge({\n  signingSecret: process.env.SLACK_SIGNING_SECRET!,\n  botToken: process.env.SLACK_BOT_TOKEN!,\n  port: 8080,\n  path: '/webhooks/slack/lists',\n  async handler(event) {\n    // Handle event\n  },\n});\n```\n\n## API Reference\n\n### Types\n\n#### `SlackListEvent`\n\n```typescript\ninterface SlackListEvent {\n  listId: string;\n  itemId: string;\n  title: string;\n  fields: Record<string, any>;\n  createdBy: string;\n  rawPayload: any;\n}\n```\n\n#### `BridgeConfig`\n\n```typescript\ninterface BridgeConfig {\n  port?: number; // Default: 3000\n  path?: string; // Default: '/slack/list-webhook'\n  signingSecret: string;\n  botToken: string;\n  handler: (event: SlackListEvent) => Promise<void>;\n}\n```\n\n#### `SlackListBridge`\n\n```typescript\ninterface SlackListBridge {\n  stop(): Promise<void>;\n}\n```\n\n### Functions\n\n#### `createSlackListBridge(config: BridgeConfig): SlackListBridge`\n\nCreates and starts a Slack list bridge server.\n\n**Parameters:**\n- `config` - Bridge configuration\n\n**Returns:**\n- Bridge instance with `stop()` method\n\n**Example:**\n```typescript\nconst bridge = createSlackListBridge({\n  signingSecret: 'your-signing-secret',\n  botToken: 'xoxb-your-bot-token',\n  handler: async (event) => {\n    console.log(event);\n  },\n});\n```\n\n#### `updateSlackListItem(client: WebClient, listId: string, itemId: string, updates: Record<string, any>): Promise<any>`\n\nUpdates fields on a Slack list item.\n\n**Parameters:**\n- `client` - Slack WebClient instance\n- `listId` - List ID\n- `itemId` - Item ID\n- `updates` - Fields to update\n\n**Returns:**\n- API response\n\n**Example:**\n```typescript\nawait updateSlackListItem(client, 'L123', 'I456', {\n  status: 'completed',\n  result: 'success',\n});\n```\n\n#### `addSlackListComment(client: WebClient, listId: string, itemId: string, comment: string): Promise<any>`\n\nAdds a comment to a Slack list item.\n\n**Parameters:**\n- `client` - Slack WebClient instance\n- `listId` - List ID\n- `itemId` - Item ID\n- `comment` - Comment text\n\n**Returns:**\n- API response\n\n**Example:**\n```typescript\nawait addSlackListComment(client, 'L123', 'I456', 'Processing complete!');\n```\n\n#### `completeSlackListItem(client: WebClient, listId: string, itemId: string): Promise<any>`\n\nMarks a Slack list item as complete.\n\n**Parameters:**\n- `client` - Slack WebClient instance\n- `listId` - List ID\n- `itemId` - Item ID\n\n**Returns:**\n- API response\n\n**Example:**\n```typescript\nawait completeSlackListItem(client, 'L123', 'I456');\n```\n\n#### `verifySlackSignature(signingSecret: string, requestSignature: string, timestamp: string, body: string): boolean`\n\nVerifies a Slack request signature (used internally by the bridge).\n\n**Parameters:**\n- `signingSecret` - Slack signing secret\n- `requestSignature` - Signature from `x-slack-signature` header\n- `timestamp` - Timestamp from `x-slack-request-timestamp` header\n- `body` - Raw request body as string\n\n**Returns:**\n- `true` if signature is valid, `false` otherwise\n\n#### `parseSlackListEvent(rawPayload: any): SlackListEvent`\n\nParses and validates a Slack list event payload (used internally by the bridge).\n\n**Parameters:**\n- `rawPayload` - Raw payload from Slack webhook\n\n**Returns:**\n- Parsed and type-safe event object\n\n**Throws:**\n- Error if payload is invalid\n\n## Setting Up in Slack\n\n1. Create a Slack app at https://api.slack.com/apps\n2. Enable \"Event Subscriptions\" and set your webhook URL\n3. Subscribe to list events\n4. Install the app to your workspace\n5. Copy the signing secret and bot token\n\n## Security\n\n- All requests are verified using Slack's signature verification\n- Timestamps are checked to prevent replay attacks (5-minute window)\n- Signatures are compared using timing-safe comparison\n\n## Error Handling\n\nThe bridge handles errors gracefully:\n\n- Missing signature headers → 401 Unauthorized\n- Invalid signature → 401 Unauthorized\n- Invalid payload → 500 Internal Server Error\n- Handler errors → 500 Internal Server Error (logged)\n\n## Testing\n\n```bash\nnpm run test\nnpm run test:coverage\n```\n\n## License\n\nCopyright (c) 2025 Bernier LLC. This file is licensed to the client under a limited-use license.\n","readmeFilename":"README.md"}