@tagma/trigger-webhook 0.2.1 → 0.2.2
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/README.md +12 -10
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -20
- package/dist/index.js.map +1 -1
- package/dist/index.test.d.ts +2 -0
- package/dist/index.test.d.ts.map +1 -0
- package/dist/index.test.js +14 -0
- package/dist/index.test.js.map +1 -0
- package/package.json +3 -6
- package/src/index.test.ts +15 -0
- package/src/index.ts +1 -20
package/README.md
CHANGED
|
@@ -55,24 +55,26 @@ await loadPlugins(['@tagma/trigger-webhook']);
|
|
|
55
55
|
|
|
56
56
|
## Config
|
|
57
57
|
|
|
58
|
-
| Field | Type | Default | Notes
|
|
59
|
-
| ------------ | -------- | ------------ |
|
|
60
|
-
| `port` | number | _(required)_ | TCP port to listen on (1-65535)
|
|
61
|
-
| `path` | string | `/webhook` | URL path to match; must start with `/`
|
|
62
|
-
| `
|
|
63
|
-
| `
|
|
58
|
+
| Field | Type | Default | Notes |
|
|
59
|
+
| ------------ | -------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
60
|
+
| `port` | number | _(required)_ | TCP port to listen on (1-65535) |
|
|
61
|
+
| `path` | string | `/webhook` | URL path to match; must start with `/` |
|
|
62
|
+
| `host` | string | `127.0.0.1` | Interface to bind. Defaults to loopback. Setting to `0.0.0.0` or any non-loopback address without `secret_env` is refused at config time |
|
|
63
|
+
| `secret_env` | string | _(none)_ | Env var holding the HMAC-SHA256 secret. When set, requests must include `x-tagma-signature` |
|
|
64
|
+
| `timeout` | duration | _(forever)_ | Max wait time; omit (or set to `0`) for unbounded wait |
|
|
64
65
|
|
|
65
66
|
## Behavior
|
|
66
67
|
|
|
67
|
-
- A single `Bun.serve` listener is created per unique `(port, path)`
|
|
68
|
+
- A single `Bun.serve` listener is created per unique `(host, port, path)` triple and shared across all tasks that watch it. Multiple tasks on the same endpoint form a FIFO waiter queue — the next POST wakes one waiter.
|
|
69
|
+
- Default bind is `127.0.0.1` so the endpoint is only reachable from the local machine. A non-loopback `host` without `secret_env` is refused.
|
|
68
70
|
- Signature header format: `x-tagma-signature: sha256=<hex>`, HMAC-SHA256 of the raw request body using the secret. Verification is constant-time.
|
|
69
|
-
- JSON bodies (`content-type: application/json`) are parsed and handed to the task as the trigger payload
|
|
70
|
-
- A POST arriving while no task is waiting is rejected with `409 no waiting task` so the caller can retry once a pipeline is up.
|
|
71
|
+
- JSON bodies (`content-type: application/json`) are parsed and handed to the task as the trigger payload. A malformed JSON body under that content-type returns `400 invalid JSON body`. Other content-types are passed through as raw strings.
|
|
72
|
+
- Successful delivery responds `202 ok`. A POST arriving while no task is waiting is rejected with `409 no waiting task` so the caller can retry once a pipeline is up. Non-matching paths return `404`, non-POST methods return `405`.
|
|
71
73
|
- The listener outlives the task — it's a per-process singleton, not cleaned up between pipeline runs. Restart the host to free the port.
|
|
72
74
|
|
|
73
75
|
## Security
|
|
74
76
|
|
|
75
|
-
Always set `secret_env` in production. Without it,
|
|
77
|
+
Always set `secret_env` in production. Without it, any caller that can reach the loopback port can fire the trigger. The plugin already binds to `127.0.0.1` by default; only change `host` when you deliberately need LAN/container reachability, and always pair a non-loopback bind with `secret_env`.
|
|
76
78
|
|
|
77
79
|
## License
|
|
78
80
|
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAqB,KAAK,aAAa,EAAuB,MAAM,cAAc,CAAC;AAuH1F,QAAA,MAAM,cAAc,EAAE,aAwHrB,CAAC;AAGF,eAAO,MAAM,cAAc,aAAa,CAAC;AACzC,eAAO,MAAM,UAAU,YAAY,CAAC;AACpC,eAAe,cAAc,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
// path: /hooks/deploy
|
|
22
22
|
// secret_env: TAGMA_WEBHOOK_SECRET
|
|
23
23
|
// timeout: 10m
|
|
24
|
+
import { parseDurationSafe } from '@tagma/types';
|
|
24
25
|
import { createHmac, timingSafeEqual } from 'node:crypto';
|
|
25
26
|
// Module-level so concurrent tasks on the same (port, path) share one
|
|
26
27
|
// listener. Bun.serve refuses to bind a port twice, so this sharing is
|
|
@@ -30,26 +31,6 @@ function serverKey(port, path, hostname) {
|
|
|
30
31
|
return `${hostname}::${port}::${path}`;
|
|
31
32
|
}
|
|
32
33
|
const DEFAULT_WEBHOOK_HOST = '127.0.0.1';
|
|
33
|
-
function parseDurationSafe(raw, fallback) {
|
|
34
|
-
if (raw == null)
|
|
35
|
-
return fallback;
|
|
36
|
-
const str = String(raw).trim();
|
|
37
|
-
const m = str.match(/^(\d+(?:\.\d+)?)(ms|s|m|h)?$/);
|
|
38
|
-
if (!m)
|
|
39
|
-
return fallback;
|
|
40
|
-
const n = Number(m[1]);
|
|
41
|
-
switch (m[2]) {
|
|
42
|
-
case 'ms':
|
|
43
|
-
return n;
|
|
44
|
-
case 'm':
|
|
45
|
-
return n * 60_000;
|
|
46
|
-
case 'h':
|
|
47
|
-
return n * 3_600_000;
|
|
48
|
-
case 's':
|
|
49
|
-
default:
|
|
50
|
-
return n * 1000;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
34
|
function verifySignature(rawBody, header, secret) {
|
|
54
35
|
const expected = 'sha256=' + createHmac('sha256', secret).update(rawBody).digest('hex');
|
|
55
36
|
const a = Buffer.from(header);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,EAAE;AACF,0EAA0E;AAC1E,0EAA0E;AAC1E,4EAA4E;AAC5E,0CAA0C;AAC1C,EAAE;AACF,4EAA4E;AAC5E,4EAA4E;AAC5E,4EAA4E;AAC5E,gCAAgC;AAChC,EAAE;AACF,0BAA0B;AAC1B,wCAAwC;AACxC,YAAY;AACZ,eAAe;AACf,uBAAuB;AACvB,qBAAqB;AACrB,4BAA4B;AAC5B,yBAAyB;AACzB,kCAAkC;AAClC,+CAA+C;AAC/C,2BAA2B;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { describe, expect, test } from 'bun:test';
|
|
2
|
+
import plugin from './index';
|
|
3
|
+
import manifest from '../package.json' with { type: 'json' };
|
|
4
|
+
describe('trigger-webhook plugin shape', () => {
|
|
5
|
+
test('manifest declares triggers/webhook and matches plugin.name', () => {
|
|
6
|
+
expect(manifest.tagmaPlugin.category).toBe('triggers');
|
|
7
|
+
expect(manifest.tagmaPlugin.type).toBe('webhook');
|
|
8
|
+
expect(plugin.name).toBe(manifest.tagmaPlugin.type);
|
|
9
|
+
});
|
|
10
|
+
test('exposes watch function', () => {
|
|
11
|
+
expect(typeof plugin.watch).toBe('function');
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
//# sourceMappingURL=index.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,MAAM,MAAM,SAAS,CAAC;AAC7B,OAAO,QAAQ,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAE7D,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;IAC5C,IAAI,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACtE,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACvD,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAClD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAClC,MAAM,CAAC,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tagma/trigger-webhook",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "HTTP webhook trigger plugin for tagma-sdk pipelines",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -45,13 +45,10 @@
|
|
|
45
45
|
},
|
|
46
46
|
"scripts": {
|
|
47
47
|
"build": "tsc -p tsconfig.json",
|
|
48
|
+
"test": "bun test",
|
|
48
49
|
"prepublishOnly": "bun run build"
|
|
49
50
|
},
|
|
50
51
|
"peerDependencies": {
|
|
51
|
-
"@tagma/types": "0.4.
|
|
52
|
-
},
|
|
53
|
-
"devDependencies": {
|
|
54
|
-
"bun-types": "^1.3.11",
|
|
55
|
-
"typescript": "^5.8.3"
|
|
52
|
+
"@tagma/types": "0.4.3"
|
|
56
53
|
}
|
|
57
54
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { describe, expect, test } from 'bun:test';
|
|
2
|
+
import plugin from './index';
|
|
3
|
+
import manifest from '../package.json' with { type: 'json' };
|
|
4
|
+
|
|
5
|
+
describe('trigger-webhook plugin shape', () => {
|
|
6
|
+
test('manifest declares triggers/webhook and matches plugin.name', () => {
|
|
7
|
+
expect(manifest.tagmaPlugin.category).toBe('triggers');
|
|
8
|
+
expect(manifest.tagmaPlugin.type).toBe('webhook');
|
|
9
|
+
expect(plugin.name).toBe(manifest.tagmaPlugin.type);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test('exposes watch function', () => {
|
|
13
|
+
expect(typeof plugin.watch).toBe('function');
|
|
14
|
+
});
|
|
15
|
+
});
|
package/src/index.ts
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
// secret_env: TAGMA_WEBHOOK_SECRET
|
|
23
23
|
// timeout: 10m
|
|
24
24
|
|
|
25
|
-
import type
|
|
25
|
+
import { parseDurationSafe, type TriggerPlugin, type TriggerContext } from '@tagma/types';
|
|
26
26
|
import { createHmac, timingSafeEqual } from 'node:crypto';
|
|
27
27
|
|
|
28
28
|
type Resolver = (payload: unknown) => void;
|
|
@@ -45,25 +45,6 @@ function serverKey(port: number, path: string, hostname: string): string {
|
|
|
45
45
|
|
|
46
46
|
const DEFAULT_WEBHOOK_HOST = '127.0.0.1';
|
|
47
47
|
|
|
48
|
-
function parseDurationSafe(raw: unknown, fallback: number): number {
|
|
49
|
-
if (raw == null) return fallback;
|
|
50
|
-
const str = String(raw).trim();
|
|
51
|
-
const m = str.match(/^(\d+(?:\.\d+)?)(ms|s|m|h)?$/);
|
|
52
|
-
if (!m) return fallback;
|
|
53
|
-
const n = Number(m[1]);
|
|
54
|
-
switch (m[2]) {
|
|
55
|
-
case 'ms':
|
|
56
|
-
return n;
|
|
57
|
-
case 'm':
|
|
58
|
-
return n * 60_000;
|
|
59
|
-
case 'h':
|
|
60
|
-
return n * 3_600_000;
|
|
61
|
-
case 's':
|
|
62
|
-
default:
|
|
63
|
-
return n * 1000;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
48
|
function verifySignature(rawBody: string, header: string, secret: string): boolean {
|
|
68
49
|
const expected = 'sha256=' + createHmac('sha256', secret).update(rawBody).digest('hex');
|
|
69
50
|
const a = Buffer.from(header);
|