@iveri/contracts 0.2.0 → 0.4.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/README.md +58 -12
- package/dist/cjs/api/conduit/capture.type.d.ts +70 -0
- package/dist/cjs/api/conduit/capture.type.d.ts.map +1 -0
- package/dist/cjs/api/conduit/capture.type.js +3 -0
- package/dist/cjs/api/conduit/capture.type.js.map +1 -0
- package/dist/cjs/api/conduit/endpoint.type.d.ts +66 -0
- package/dist/cjs/api/conduit/endpoint.type.d.ts.map +1 -0
- package/dist/cjs/api/conduit/endpoint.type.js +3 -0
- package/dist/cjs/api/conduit/endpoint.type.js.map +1 -0
- package/dist/cjs/api/conduit/handshake-kind.enum.d.ts +22 -0
- package/dist/cjs/api/conduit/handshake-kind.enum.d.ts.map +1 -0
- package/dist/cjs/api/conduit/handshake-kind.enum.js +26 -0
- package/dist/cjs/api/conduit/handshake-kind.enum.js.map +1 -0
- package/dist/cjs/api/conduit/index.d.ts +11 -0
- package/dist/cjs/api/conduit/index.d.ts.map +1 -0
- package/dist/cjs/api/conduit/index.js +27 -0
- package/dist/cjs/api/conduit/index.js.map +1 -0
- package/dist/cjs/api/conduit/provider.type.d.ts +138 -0
- package/dist/cjs/api/conduit/provider.type.d.ts.map +1 -0
- package/dist/cjs/api/conduit/provider.type.js +8 -0
- package/dist/cjs/api/conduit/provider.type.js.map +1 -0
- package/dist/cjs/api/conduit/replay.type.d.ts +48 -0
- package/dist/cjs/api/conduit/replay.type.d.ts.map +1 -0
- package/dist/cjs/api/conduit/replay.type.js +3 -0
- package/dist/cjs/api/conduit/replay.type.js.map +1 -0
- package/dist/cjs/api/conduit/signature-algorithm.enum.d.ts +17 -0
- package/dist/cjs/api/conduit/signature-algorithm.enum.d.ts.map +1 -0
- package/dist/cjs/api/conduit/signature-algorithm.enum.js +21 -0
- package/dist/cjs/api/conduit/signature-algorithm.enum.js.map +1 -0
- package/dist/cjs/api/conduit/signature-encoding.enum.d.ts +13 -0
- package/dist/cjs/api/conduit/signature-encoding.enum.d.ts.map +1 -0
- package/dist/cjs/api/conduit/signature-encoding.enum.js +17 -0
- package/dist/cjs/api/conduit/signature-encoding.enum.js.map +1 -0
- package/dist/cjs/api/conduit/signature-header-scheme.enum.d.ts +19 -0
- package/dist/cjs/api/conduit/signature-header-scheme.enum.d.ts.map +1 -0
- package/dist/cjs/api/conduit/signature-header-scheme.enum.js +23 -0
- package/dist/cjs/api/conduit/signature-header-scheme.enum.js.map +1 -0
- package/dist/cjs/api/conduit/signature-verdict.enum.d.ts +50 -0
- package/dist/cjs/api/conduit/signature-verdict.enum.d.ts.map +1 -0
- package/dist/cjs/api/conduit/signature-verdict.enum.js +54 -0
- package/dist/cjs/api/conduit/signature-verdict.enum.js.map +1 -0
- package/dist/cjs/api/conduit/signature.type.d.ts +54 -0
- package/dist/cjs/api/conduit/signature.type.d.ts.map +1 -0
- package/dist/cjs/api/conduit/signature.type.js +3 -0
- package/dist/cjs/api/conduit/signature.type.js.map +1 -0
- package/dist/cjs/api/identity/auth.type.d.ts +92 -0
- package/dist/cjs/api/identity/auth.type.d.ts.map +1 -0
- package/dist/cjs/api/identity/auth.type.js +3 -0
- package/dist/cjs/api/identity/auth.type.js.map +1 -0
- package/dist/cjs/api/identity/index.d.ts +4 -0
- package/dist/cjs/api/identity/index.d.ts.map +1 -0
- package/dist/cjs/api/identity/index.js +20 -0
- package/dist/cjs/api/identity/index.js.map +1 -0
- package/dist/cjs/api/identity/membership-status.enum.d.ts +16 -0
- package/dist/cjs/api/identity/membership-status.enum.d.ts.map +1 -0
- package/dist/cjs/api/identity/membership-status.enum.js +20 -0
- package/dist/cjs/api/identity/membership-status.enum.js.map +1 -0
- package/dist/cjs/api/identity/tenant-status.enum.d.ts +28 -0
- package/dist/cjs/api/identity/tenant-status.enum.d.ts.map +1 -0
- package/dist/cjs/api/identity/tenant-status.enum.js +32 -0
- package/dist/cjs/api/identity/tenant-status.enum.js.map +1 -0
- package/dist/cjs/enum/user-permission.enum.d.ts +30 -1
- package/dist/cjs/enum/user-permission.enum.d.ts.map +1 -1
- package/dist/cjs/enum/user-permission.enum.js +32 -0
- package/dist/cjs/enum/user-permission.enum.js.map +1 -1
- package/dist/cjs/type/api-response.type.d.ts +24 -28
- package/dist/cjs/type/api-response.type.d.ts.map +1 -1
- package/dist/cjs/type/index.d.ts +1 -0
- package/dist/cjs/type/index.d.ts.map +1 -1
- package/dist/cjs/type/index.js +1 -0
- package/dist/cjs/type/index.js.map +1 -1
- package/dist/cjs/type/iso-date-time.type.d.ts +17 -0
- package/dist/cjs/type/iso-date-time.type.d.ts.map +1 -0
- package/dist/cjs/type/iso-date-time.type.js +3 -0
- package/dist/cjs/type/iso-date-time.type.js.map +1 -0
- package/dist/esm/api/conduit/capture.type.d.ts +70 -0
- package/dist/esm/api/conduit/capture.type.d.ts.map +1 -0
- package/dist/esm/api/conduit/capture.type.js +2 -0
- package/dist/esm/api/conduit/capture.type.js.map +1 -0
- package/dist/esm/api/conduit/endpoint.type.d.ts +66 -0
- package/dist/esm/api/conduit/endpoint.type.d.ts.map +1 -0
- package/dist/esm/api/conduit/endpoint.type.js +2 -0
- package/dist/esm/api/conduit/endpoint.type.js.map +1 -0
- package/dist/esm/api/conduit/handshake-kind.enum.d.ts +22 -0
- package/dist/esm/api/conduit/handshake-kind.enum.d.ts.map +1 -0
- package/dist/esm/api/conduit/handshake-kind.enum.js +23 -0
- package/dist/esm/api/conduit/handshake-kind.enum.js.map +1 -0
- package/dist/esm/api/conduit/index.d.ts +11 -0
- package/dist/esm/api/conduit/index.d.ts.map +1 -0
- package/dist/esm/api/conduit/index.js +11 -0
- package/dist/esm/api/conduit/index.js.map +1 -0
- package/dist/esm/api/conduit/provider.type.d.ts +138 -0
- package/dist/esm/api/conduit/provider.type.d.ts.map +1 -0
- package/dist/esm/api/conduit/provider.type.js +5 -0
- package/dist/esm/api/conduit/provider.type.js.map +1 -0
- package/dist/esm/api/conduit/replay.type.d.ts +48 -0
- package/dist/esm/api/conduit/replay.type.d.ts.map +1 -0
- package/dist/esm/api/conduit/replay.type.js +2 -0
- package/dist/esm/api/conduit/replay.type.js.map +1 -0
- package/dist/esm/api/conduit/signature-algorithm.enum.d.ts +17 -0
- package/dist/esm/api/conduit/signature-algorithm.enum.d.ts.map +1 -0
- package/dist/esm/api/conduit/signature-algorithm.enum.js +18 -0
- package/dist/esm/api/conduit/signature-algorithm.enum.js.map +1 -0
- package/dist/esm/api/conduit/signature-encoding.enum.d.ts +13 -0
- package/dist/esm/api/conduit/signature-encoding.enum.d.ts.map +1 -0
- package/dist/esm/api/conduit/signature-encoding.enum.js +14 -0
- package/dist/esm/api/conduit/signature-encoding.enum.js.map +1 -0
- package/dist/esm/api/conduit/signature-header-scheme.enum.d.ts +19 -0
- package/dist/esm/api/conduit/signature-header-scheme.enum.d.ts.map +1 -0
- package/dist/esm/api/conduit/signature-header-scheme.enum.js +20 -0
- package/dist/esm/api/conduit/signature-header-scheme.enum.js.map +1 -0
- package/dist/esm/api/conduit/signature-verdict.enum.d.ts +50 -0
- package/dist/esm/api/conduit/signature-verdict.enum.d.ts.map +1 -0
- package/dist/esm/api/conduit/signature-verdict.enum.js +51 -0
- package/dist/esm/api/conduit/signature-verdict.enum.js.map +1 -0
- package/dist/esm/api/conduit/signature.type.d.ts +54 -0
- package/dist/esm/api/conduit/signature.type.d.ts.map +1 -0
- package/dist/esm/api/conduit/signature.type.js +2 -0
- package/dist/esm/api/conduit/signature.type.js.map +1 -0
- package/dist/esm/api/identity/auth.type.d.ts +92 -0
- package/dist/esm/api/identity/auth.type.d.ts.map +1 -0
- package/dist/esm/api/identity/auth.type.js +2 -0
- package/dist/esm/api/identity/auth.type.js.map +1 -0
- package/dist/esm/api/identity/index.d.ts +4 -0
- package/dist/esm/api/identity/index.d.ts.map +1 -0
- package/dist/esm/api/identity/index.js +4 -0
- package/dist/esm/api/identity/index.js.map +1 -0
- package/dist/esm/api/identity/membership-status.enum.d.ts +16 -0
- package/dist/esm/api/identity/membership-status.enum.d.ts.map +1 -0
- package/dist/esm/api/identity/membership-status.enum.js +17 -0
- package/dist/esm/api/identity/membership-status.enum.js.map +1 -0
- package/dist/esm/api/identity/tenant-status.enum.d.ts +28 -0
- package/dist/esm/api/identity/tenant-status.enum.d.ts.map +1 -0
- package/dist/esm/api/identity/tenant-status.enum.js +29 -0
- package/dist/esm/api/identity/tenant-status.enum.js.map +1 -0
- package/dist/esm/enum/user-permission.enum.d.ts +30 -1
- package/dist/esm/enum/user-permission.enum.d.ts.map +1 -1
- package/dist/esm/enum/user-permission.enum.js +32 -0
- package/dist/esm/enum/user-permission.enum.js.map +1 -1
- package/dist/esm/type/api-response.type.d.ts +24 -28
- package/dist/esm/type/api-response.type.d.ts.map +1 -1
- package/dist/esm/type/index.d.ts +1 -0
- package/dist/esm/type/index.d.ts.map +1 -1
- package/dist/esm/type/index.js +1 -0
- package/dist/esm/type/index.js.map +1 -1
- package/dist/esm/type/iso-date-time.type.d.ts +17 -0
- package/dist/esm/type/iso-date-time.type.d.ts.map +1 -0
- package/dist/esm/type/iso-date-time.type.js +2 -0
- package/dist/esm/type/iso-date-time.type.js.map +1 -0
- package/package.json +22 -2
package/README.md
CHANGED
|
@@ -8,10 +8,20 @@ pnpm add @iveri/contracts
|
|
|
8
8
|
```
|
|
9
9
|
|
|
10
10
|
```ts
|
|
11
|
-
|
|
11
|
+
// Cross-service primitives.
|
|
12
|
+
import { CursorPage, ErrorCode, Maybe, Paginated, UUID, UserPermission } from '@iveri/contracts';
|
|
13
|
+
|
|
14
|
+
// One service's wire surface.
|
|
15
|
+
import type { CaptureSummary, Endpoint } from '@iveri/contracts/conduit';
|
|
16
|
+
import type { AuthSession, Principal } from '@iveri/contracts/identity';
|
|
12
17
|
```
|
|
13
18
|
|
|
14
|
-
|
|
19
|
+
Three entry points, and no others — never `@iveri/contracts/dist/...`.
|
|
20
|
+
|
|
21
|
+
The per-service surfaces are **not** re-exported from the root, deliberately. Conduit owns a
|
|
22
|
+
`Provider` and an `Endpoint`; Unibox will want both names for entirely different things. Keeping
|
|
23
|
+
each service behind its own entry point means that collision never has to be resolved by
|
|
24
|
+
renaming a type in a shipped API.
|
|
15
25
|
|
|
16
26
|
## Zero runtime dependencies — the rule that defines this package
|
|
17
27
|
|
|
@@ -31,13 +41,14 @@ Anything needing a dependency belongs in `@iveri/nest-sdk` (backend) or `@iveri/
|
|
|
31
41
|
|
|
32
42
|
### `type/`
|
|
33
43
|
|
|
34
|
-
| Type
|
|
35
|
-
|
|
|
36
|
-
| `Nil`, `Maybe<T>`, `Nullable<T>`
|
|
37
|
-
| `UUID`
|
|
38
|
-
| `Paginated<T>`
|
|
39
|
-
| `CursorPage<T>`
|
|
40
|
-
| `
|
|
44
|
+
| Type | Use |
|
|
45
|
+
| ---------------------------------- | --------------------------------------------------------------------------------------------- |
|
|
46
|
+
| `Nil`, `Maybe<T>`, `Nullable<T>` | absent values. `Nullable` for anything crossing the wire — `JSON.stringify` drops `undefined` |
|
|
47
|
+
| `UUID` | template-literal shape hint; validation stays at the edge with `@IsUUID()` |
|
|
48
|
+
| `Paginated<T>` | offset paging, where the client needs a total or arbitrary page jumps |
|
|
49
|
+
| `CursorPage<T>` | cursor paging — the default for lists that grow while being read |
|
|
50
|
+
| `IsoDateTime` | a timestamp as it appears on the wire. JSON has no date type — this is a `string` |
|
|
51
|
+
| `ApiErrorResponse`, `ApiErrorBody` | the error envelope. **Only errors are enveloped**; a success is the bare payload |
|
|
41
52
|
|
|
42
53
|
### `enum/`
|
|
43
54
|
|
|
@@ -55,11 +66,38 @@ Values are `<resource>:<action>`, or `<service>:<resource>:<action>` where a res
|
|
|
55
66
|
would otherwise collide — identity's members are unprefixed because they predate the shared
|
|
56
67
|
catalogue and are already embedded in issued tokens and stored role rows.
|
|
57
68
|
|
|
69
|
+
### `api/identity/` → `@iveri/contracts/identity`
|
|
70
|
+
|
|
71
|
+
`iveri-identity-api`'s authentication surface: `SignupBody`, `LoginBody`, `RefreshTokenBody`,
|
|
72
|
+
`AcceptInvitationBody`, `AuthTokens`, `Principal`, `AuthSession`, plus `TenantStatus` and
|
|
73
|
+
`MembershipStatus`.
|
|
74
|
+
|
|
75
|
+
Auth only. Identity also exposes tenant, user, membership, role and API-key routes; those have
|
|
76
|
+
one consumer each and stay in the service until a second one appears.
|
|
77
|
+
|
|
78
|
+
### `api/conduit/` → `@iveri/contracts/conduit`
|
|
79
|
+
|
|
80
|
+
`conduit-api`'s full admin surface: `Endpoint`, `CaptureSummary`/`CaptureDetail`, `Provider`
|
|
81
|
+
with its `SignatureManifest`/`HandshakeManifest`, `Replay`, `SignatureDiagnostic`, the request
|
|
82
|
+
bodies for each, and the five enums they are built from — `SignatureVerdict`,
|
|
83
|
+
`SignatureAlgorithm`, `SignatureEncoding`, `SignatureHeaderScheme`, `HandshakeKind`.
|
|
84
|
+
|
|
85
|
+
### Why the wire shapes moved here
|
|
86
|
+
|
|
87
|
+
`conduit-admin-web` hand-transcribed all of it, carefully and with comments. It still drifted:
|
|
88
|
+
`TenantStatus` was written `'active' | 'suspended' | 'cancelled'` where identity sends
|
|
89
|
+
`'ACTIVE' | 'SUSPENDED' | 'PENDING_DELETION'` — wrong casing, and a member that has never
|
|
90
|
+
existed — and `bodySha256` was missing from two shapes. Nothing caught any of it, because a
|
|
91
|
+
hand-written mirror is checked by nobody.
|
|
92
|
+
|
|
93
|
+
Both sides now compile against these types: each service's response DTO `implements` the
|
|
94
|
+
interface it fulfils, so a field renamed in `conduit-api` fails `tsc` in `conduit-api` rather
|
|
95
|
+
than surfacing as `undefined` in a panel weeks later.
|
|
96
|
+
|
|
58
97
|
## What is deliberately **not** here yet
|
|
59
98
|
|
|
60
|
-
`event/`
|
|
61
|
-
|
|
62
|
-
needs them, per the second-consumer rule — not in anticipation.
|
|
99
|
+
`event/` — the domain event envelope and topic map. No service publishes one yet; it lands with
|
|
100
|
+
Conduit's outbox.
|
|
63
101
|
|
|
64
102
|
## Adding to the contract
|
|
65
103
|
|
|
@@ -67,9 +105,17 @@ needs them, per the second-consumer rule — not in anticipation.
|
|
|
67
105
|
existing member means, or removing one, is **major** — clients branch on these, and a
|
|
68
106
|
removed permission silently downgrades every live session whose token still carries it.
|
|
69
107
|
- Widening a type is minor; narrowing it is major.
|
|
108
|
+
- Under `api/`, the contract follows the service: add the field to the service's DTO and to the
|
|
109
|
+
interface in the same release, and let `implements` prove they agree.
|
|
70
110
|
- Breaking changes get a migration note in `CHANGELOG.md`. Services upgrade deliberately.
|
|
71
111
|
|
|
72
112
|
## Build output
|
|
73
113
|
|
|
74
114
|
Dual ESM + CJS (`dist/esm`, `dist/cjs`) behind an `exports` map, so NestJS `require`s it and
|
|
75
115
|
Vite tree-shakes it. `sideEffects: false`.
|
|
116
|
+
|
|
117
|
+
The subpath entry points also need a `typesVersions` block, because **TypeScript only reads
|
|
118
|
+
`exports` under `moduleResolution` `node16`/`nodenext`/`bundler`** and every Nest service in the
|
|
119
|
+
fleet compiles with `"node"`. Without it `@iveri/contracts/conduit` resolves at runtime and is
|
|
120
|
+
untyped at compile time — in one repo but not another, which is a confusing thing to debug.
|
|
121
|
+
`scripts/verify-entry-points.mjs` runs in `build` and fails if either half is missing.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { CursorPage } from '../../type/cursor-page.type.js';
|
|
2
|
+
import type { IsoDateTime } from '../../type/iso-date-time.type.js';
|
|
3
|
+
import type { Nullable } from '../../type/nil.type.js';
|
|
4
|
+
import type { UUID } from '../../type/uuid.type.js';
|
|
5
|
+
import type { SignatureVerdict } from './signature-verdict.enum.js';
|
|
6
|
+
/** A capture without its body — one row of the list. */
|
|
7
|
+
export interface CaptureSummary {
|
|
8
|
+
id: UUID;
|
|
9
|
+
endpointId: UUID;
|
|
10
|
+
method: string;
|
|
11
|
+
/** Path after the ingress token. */
|
|
12
|
+
path: string;
|
|
13
|
+
/** Raw query string, without the `?`. */
|
|
14
|
+
queryString: string;
|
|
15
|
+
contentType: Nullable<string>;
|
|
16
|
+
/** Body size in bytes, as received. */
|
|
17
|
+
bodySize: number;
|
|
18
|
+
/** Hex SHA-256 of the body. Compare this against what the provider says it sent. */
|
|
19
|
+
bodySha256: string;
|
|
20
|
+
/** From `x-forwarded-for`. Advisory — a client controls it. */
|
|
21
|
+
sourceIp: Nullable<string>;
|
|
22
|
+
/**
|
|
23
|
+
* Verdict recorded **when the request arrived**. A snapshot: fixing the endpoint's secret
|
|
24
|
+
* does not rewrite it. Re-run the signature route to check against current configuration.
|
|
25
|
+
*/
|
|
26
|
+
signatureVerdict: Nullable<SignatureVerdict>;
|
|
27
|
+
/** A provider's URL-verification challenge rather than a real event. */
|
|
28
|
+
isHandshake: boolean;
|
|
29
|
+
receivedAt: IsoDateTime;
|
|
30
|
+
}
|
|
31
|
+
/** A capture with its headers and body. `GET /api/v1/capture/:id`. */
|
|
32
|
+
export interface CaptureDetail extends CaptureSummary {
|
|
33
|
+
/** Every request header, lowercase keys — including the signature headers. */
|
|
34
|
+
headers: Record<string, string | string[]>;
|
|
35
|
+
/**
|
|
36
|
+
* The body as UTF-8 when it decodes cleanly, otherwise `null`.
|
|
37
|
+
*
|
|
38
|
+
* A convenience only. `toString('utf8')` never fails — it substitutes U+FFFD for every
|
|
39
|
+
* invalid sequence — so a gzip or protobuf body would come back as convincing-looking
|
|
40
|
+
* mojibake that no longer hashes to `bodySha256`. Conduit round-trips the decode and sends
|
|
41
|
+
* `null` when it does not survive, which is the honest answer.
|
|
42
|
+
*/
|
|
43
|
+
body: Nullable<string>;
|
|
44
|
+
/**
|
|
45
|
+
* The body as base64. **This is the authoritative field.** A webhook body is arbitrary
|
|
46
|
+
* bytes; base64 is the only representation that survives JSON without alteration, and the
|
|
47
|
+
* signed payload is those exact bytes.
|
|
48
|
+
*/
|
|
49
|
+
bodyBase64: string;
|
|
50
|
+
/** The body was too large to inline and was read back from a spill file. */
|
|
51
|
+
isSpilled: boolean;
|
|
52
|
+
}
|
|
53
|
+
/** `GET /api/v1/capture`. */
|
|
54
|
+
export type CapturesPage = CursorPage<CaptureSummary>;
|
|
55
|
+
/**
|
|
56
|
+
* Query for `GET /api/v1/capture`.
|
|
57
|
+
*
|
|
58
|
+
* Cursor-paginated, unlike endpoints and providers: captures are appended to while they are
|
|
59
|
+
* being read — every inbound webhook lands at the top of the list, including while an operator
|
|
60
|
+
* pages through it — and offset paging drops or repeats rows under that.
|
|
61
|
+
*/
|
|
62
|
+
export interface GetCapturesQuery {
|
|
63
|
+
limit?: number;
|
|
64
|
+
/** Opaque cursor from the previous page's `nextCursor`. Never parse it. */
|
|
65
|
+
after?: Nullable<string>;
|
|
66
|
+
endpointId?: Nullable<UUID>;
|
|
67
|
+
method?: Nullable<string>;
|
|
68
|
+
signatureVerdict?: Nullable<SignatureVerdict>;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=capture.type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capture.type.d.ts","sourceRoot":"","sources":["../../../../src/api/conduit/capture.type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAEpD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAEpE,wDAAwD;AACxD,MAAM,WAAW,cAAc;IAC3B,EAAE,EAAE,IAAI,CAAC;IACT,UAAU,EAAE,IAAI,CAAC;IAEjB,MAAM,EAAE,MAAM,CAAC;IAEf,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;IAEb,yCAAyC;IACzC,WAAW,EAAE,MAAM,CAAC;IAEpB,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAE9B,uCAAuC;IACvC,QAAQ,EAAE,MAAM,CAAC;IAEjB,oFAAoF;IACpF,UAAU,EAAE,MAAM,CAAC;IAEnB,+DAA+D;IAC/D,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAE3B;;;OAGG;IACH,gBAAgB,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IAE7C,wEAAwE;IACxE,WAAW,EAAE,OAAO,CAAC;IAErB,UAAU,EAAE,WAAW,CAAC;CAC3B;AAED,sEAAsE;AACtE,MAAM,WAAW,aAAc,SAAQ,cAAc;IACjD,8EAA8E;IAC9E,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAE3C;;;;;;;OAOG;IACH,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAEvB;;;;OAIG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB,4EAA4E;IAC5E,SAAS,EAAE,OAAO,CAAC;CACtB;AAED,6BAA6B;AAC7B,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,cAAc,CAAC,CAAC;AAEtD;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,2EAA2E;IAC3E,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAEzB,UAAU,CAAC,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC5B,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC1B,gBAAgB,CAAC,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAAC;CACjD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capture.type.js","sourceRoot":"","sources":["../../../../src/api/conduit/capture.type.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { IsoDateTime } from '../../type/iso-date-time.type.js';
|
|
2
|
+
import type { Nullable } from '../../type/nil.type.js';
|
|
3
|
+
import type { Paginated } from '../../type/paginated.type.js';
|
|
4
|
+
import type { UUID } from '../../type/uuid.type.js';
|
|
5
|
+
/**
|
|
6
|
+
* One endpoint on the wire.
|
|
7
|
+
*
|
|
8
|
+
* Carries `hasSigningSecret`, never the secret. Not a masked value, not a last-four hint — the
|
|
9
|
+
* field simply does not exist, so no future change can accidentally start populating it.
|
|
10
|
+
*/
|
|
11
|
+
export interface Endpoint {
|
|
12
|
+
id: UUID;
|
|
13
|
+
name: string;
|
|
14
|
+
description: Nullable<string>;
|
|
15
|
+
/** The path segment providers post to. */
|
|
16
|
+
ingressToken: string;
|
|
17
|
+
/**
|
|
18
|
+
* Path to register with the provider. Relative on purpose — the public origin is a tunnel or
|
|
19
|
+
* a load balancer this service cannot see, so the caller prepends its own.
|
|
20
|
+
*/
|
|
21
|
+
ingressPath: string;
|
|
22
|
+
providerKey: Nullable<string>;
|
|
23
|
+
/** Whether a signing secret is configured. The secret itself is never returned. */
|
|
24
|
+
hasSigningSecret: boolean;
|
|
25
|
+
/** Whether a handshake verify token is configured. */
|
|
26
|
+
hasVerifyToken: boolean;
|
|
27
|
+
/** Inactive endpoints answer 410 Gone. */
|
|
28
|
+
isActive: boolean;
|
|
29
|
+
createdAt: IsoDateTime;
|
|
30
|
+
updatedAt: IsoDateTime;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* `GET /api/v1/endpoint`. Offset-paginated, unlike captures: endpoints are a small, slow-moving
|
|
34
|
+
* collection a customer renders as numbered pages.
|
|
35
|
+
*/
|
|
36
|
+
export type EndpointsPage = Paginated<Endpoint>;
|
|
37
|
+
/** `POST /api/v1/endpoint`. */
|
|
38
|
+
export interface CreateEndpointBody {
|
|
39
|
+
name: string;
|
|
40
|
+
description?: Nullable<string>;
|
|
41
|
+
providerKey?: Nullable<string>;
|
|
42
|
+
signingSecret?: Nullable<string>;
|
|
43
|
+
verifyToken?: Nullable<string>;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* `PATCH /api/v1/endpoint/:id`.
|
|
47
|
+
*
|
|
48
|
+
* **Secret fields have three states, not two.** Omitting one leaves the stored secret untouched;
|
|
49
|
+
* sending `null` deletes it. A form must therefore never send `''` or `null` where the user
|
|
50
|
+
* meant "I did not change this" — that silently wipes a working signing secret, and the next
|
|
51
|
+
* webhook verifies as `MISSING_SECRET` with nothing to say why.
|
|
52
|
+
*/
|
|
53
|
+
export interface UpdateEndpointBody {
|
|
54
|
+
name?: string;
|
|
55
|
+
description?: Nullable<string>;
|
|
56
|
+
providerKey?: Nullable<string>;
|
|
57
|
+
signingSecret?: Nullable<string>;
|
|
58
|
+
verifyToken?: Nullable<string>;
|
|
59
|
+
isActive?: boolean;
|
|
60
|
+
}
|
|
61
|
+
/** Query for `GET /api/v1/endpoint`. */
|
|
62
|
+
export interface GetEndpointsQuery {
|
|
63
|
+
limit?: number;
|
|
64
|
+
offset?: number;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=endpoint.type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"endpoint.type.d.ts","sourceRoot":"","sources":["../../../../src/api/conduit/endpoint.type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAEpD;;;;;GAKG;AACH,MAAM,WAAW,QAAQ;IACrB,EAAE,EAAE,IAAI,CAAC;IACT,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAE9B,0CAA0C;IAC1C,YAAY,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAE9B,mFAAmF;IACnF,gBAAgB,EAAE,OAAO,CAAC;IAE1B,sDAAsD;IACtD,cAAc,EAAE,OAAO,CAAC;IAExB,0CAA0C;IAC1C,QAAQ,EAAE,OAAO,CAAC;IAElB,SAAS,EAAE,WAAW,CAAC;IACvB,SAAS,EAAE,WAAW,CAAC;CAC1B;AAED;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAEhD,+BAA+B;AAC/B,MAAM,WAAW,kBAAkB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/B,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/B,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IACjC,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;CAClC;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/B,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/B,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IACjC,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,wCAAwC;AACxC,MAAM,WAAW,iBAAiB;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"endpoint.type.js","sourceRoot":"","sources":["../../../../src/api/conduit/endpoint.type.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How a provider proves the endpoint is really ours before it will send anything.
|
|
3
|
+
*
|
|
4
|
+
* **Handshakes work in inspect mode, deliberately.** Meta will not save a callback URL that
|
|
5
|
+
* does not echo `hub.challenge`, and Slack will not save one that does not echo `challenge` —
|
|
6
|
+
* so without this, the local developer tool could never be registered with the provider at all,
|
|
7
|
+
* and there would be nothing to capture. It is the one piece of ingress behaviour that is not
|
|
8
|
+
* "store and acknowledge".
|
|
9
|
+
*/
|
|
10
|
+
export declare enum HandshakeKind {
|
|
11
|
+
/**
|
|
12
|
+
* Provider sends `GET ?mode=subscribe&verify_token=…&challenge=…` and expects the challenge
|
|
13
|
+
* echoed back as the plain-text body. Meta (WhatsApp, Messenger, Instagram).
|
|
14
|
+
*/
|
|
15
|
+
QUERY_ECHO = "query-echo",
|
|
16
|
+
/**
|
|
17
|
+
* Provider sends a JSON body carrying a trigger field and a challenge, and expects the
|
|
18
|
+
* challenge echoed in a JSON response. Slack (`type: url_verification`).
|
|
19
|
+
*/
|
|
20
|
+
JSON_ECHO = "json-echo"
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=handshake-kind.enum.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handshake-kind.enum.d.ts","sourceRoot":"","sources":["../../../../src/api/conduit/handshake-kind.enum.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,oBAAY,aAAa;IACrB;;;OAGG;IACH,UAAU,eAAe;IAEzB;;;OAGG;IACH,SAAS,cAAc;CAC1B"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HandshakeKind = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* How a provider proves the endpoint is really ours before it will send anything.
|
|
6
|
+
*
|
|
7
|
+
* **Handshakes work in inspect mode, deliberately.** Meta will not save a callback URL that
|
|
8
|
+
* does not echo `hub.challenge`, and Slack will not save one that does not echo `challenge` —
|
|
9
|
+
* so without this, the local developer tool could never be registered with the provider at all,
|
|
10
|
+
* and there would be nothing to capture. It is the one piece of ingress behaviour that is not
|
|
11
|
+
* "store and acknowledge".
|
|
12
|
+
*/
|
|
13
|
+
var HandshakeKind;
|
|
14
|
+
(function (HandshakeKind) {
|
|
15
|
+
/**
|
|
16
|
+
* Provider sends `GET ?mode=subscribe&verify_token=…&challenge=…` and expects the challenge
|
|
17
|
+
* echoed back as the plain-text body. Meta (WhatsApp, Messenger, Instagram).
|
|
18
|
+
*/
|
|
19
|
+
HandshakeKind["QUERY_ECHO"] = "query-echo";
|
|
20
|
+
/**
|
|
21
|
+
* Provider sends a JSON body carrying a trigger field and a challenge, and expects the
|
|
22
|
+
* challenge echoed in a JSON response. Slack (`type: url_verification`).
|
|
23
|
+
*/
|
|
24
|
+
HandshakeKind["JSON_ECHO"] = "json-echo";
|
|
25
|
+
})(HandshakeKind || (exports.HandshakeKind = HandshakeKind = {}));
|
|
26
|
+
//# sourceMappingURL=handshake-kind.enum.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handshake-kind.enum.js","sourceRoot":"","sources":["../../../../src/api/conduit/handshake-kind.enum.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;GAQG;AACH,IAAY,aAYX;AAZD,WAAY,aAAa;IACrB;;;OAGG;IACH,0CAAyB,CAAA;IAEzB;;;OAGG;IACH,wCAAuB,CAAA;AAC3B,CAAC,EAZW,aAAa,6BAAb,aAAa,QAYxB"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from './capture.type.js';
|
|
2
|
+
export * from './endpoint.type.js';
|
|
3
|
+
export * from './handshake-kind.enum.js';
|
|
4
|
+
export * from './provider.type.js';
|
|
5
|
+
export * from './replay.type.js';
|
|
6
|
+
export * from './signature-algorithm.enum.js';
|
|
7
|
+
export * from './signature-encoding.enum.js';
|
|
8
|
+
export * from './signature-header-scheme.enum.js';
|
|
9
|
+
export * from './signature-verdict.enum.js';
|
|
10
|
+
export * from './signature.type.js';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/api/conduit/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,mCAAmC,CAAC;AAClD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./capture.type.js"), exports);
|
|
18
|
+
__exportStar(require("./endpoint.type.js"), exports);
|
|
19
|
+
__exportStar(require("./handshake-kind.enum.js"), exports);
|
|
20
|
+
__exportStar(require("./provider.type.js"), exports);
|
|
21
|
+
__exportStar(require("./replay.type.js"), exports);
|
|
22
|
+
__exportStar(require("./signature-algorithm.enum.js"), exports);
|
|
23
|
+
__exportStar(require("./signature-encoding.enum.js"), exports);
|
|
24
|
+
__exportStar(require("./signature-header-scheme.enum.js"), exports);
|
|
25
|
+
__exportStar(require("./signature-verdict.enum.js"), exports);
|
|
26
|
+
__exportStar(require("./signature.type.js"), exports);
|
|
27
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/api/conduit/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oDAAkC;AAClC,qDAAmC;AACnC,2DAAyC;AACzC,qDAAmC;AACnC,mDAAiC;AACjC,gEAA8C;AAC9C,+DAA6C;AAC7C,oEAAkD;AAClD,8DAA4C;AAC5C,sDAAoC"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import type { IsoDateTime } from '../../type/iso-date-time.type.js';
|
|
2
|
+
import type { Nullable } from '../../type/nil.type.js';
|
|
3
|
+
import type { UUID } from '../../type/uuid.type.js';
|
|
4
|
+
import type { HandshakeKind } from './handshake-kind.enum.js';
|
|
5
|
+
import type { SignatureAlgorithm } from './signature-algorithm.enum.js';
|
|
6
|
+
import type { SignatureEncoding } from './signature-encoding.enum.js';
|
|
7
|
+
import type { SignatureHeaderScheme } from './signature-header-scheme.enum.js';
|
|
8
|
+
/** Required in `signedPayloadTemplate`; substituted with the raw request bytes. */
|
|
9
|
+
export declare const SIGNED_PAYLOAD_BODY_TOKEN = "{body}";
|
|
10
|
+
/** Optional in `signedPayloadTemplate`; substituted with the timestamp exactly as received. */
|
|
11
|
+
export declare const SIGNED_PAYLOAD_TIMESTAMP_TOKEN = "{timestamp}";
|
|
12
|
+
/**
|
|
13
|
+
* How to verify one provider's HMAC.
|
|
14
|
+
*
|
|
15
|
+
* A manifest holds **no secret**. It describes where a signature lives and how it is computed,
|
|
16
|
+
* never the key it is computed with — which is why it is returned in full to anyone with
|
|
17
|
+
* `conduit:provider:read` while the signing secret it is used against is returned to nobody.
|
|
18
|
+
*
|
|
19
|
+
* This is the response shape: every key is present, absent ones are `null`. The request shape
|
|
20
|
+
* is {@link SignatureManifestInput}, where they may be omitted.
|
|
21
|
+
*/
|
|
22
|
+
export interface SignatureManifest {
|
|
23
|
+
algorithm: SignatureAlgorithm;
|
|
24
|
+
encoding: SignatureEncoding;
|
|
25
|
+
/** Lowercase header the signature arrives in, e.g. `x-hub-signature-256`. */
|
|
26
|
+
headerName: string;
|
|
27
|
+
headerScheme: SignatureHeaderScheme;
|
|
28
|
+
/** Literal prefix stripped before comparison, e.g. `sha256=`. `DIRECT` scheme only. */
|
|
29
|
+
headerPrefix: Nullable<string>;
|
|
30
|
+
/** Key naming the signature inside a `KEY_VALUE_LIST` header, e.g. `v1`. */
|
|
31
|
+
signatureKey: Nullable<string>;
|
|
32
|
+
/** Separate header carrying the signed timestamp, when it is not in the signature header. */
|
|
33
|
+
timestampHeaderName: Nullable<string>;
|
|
34
|
+
/** Key naming the timestamp inside a `KEY_VALUE_LIST` header, e.g. `t`. */
|
|
35
|
+
timestampKey: Nullable<string>;
|
|
36
|
+
/** Replay window. Null disables the age check entirely. */
|
|
37
|
+
timestampToleranceSeconds: Nullable<number>;
|
|
38
|
+
/**
|
|
39
|
+
* What gets hashed. {@link SIGNED_PAYLOAD_BODY_TOKEN} is required;
|
|
40
|
+
* {@link SIGNED_PAYLOAD_TIMESTAMP_TOKEN} is optional — Slack's is `v0:{timestamp}:{body}`,
|
|
41
|
+
* Meta's is just `{body}`.
|
|
42
|
+
*/
|
|
43
|
+
signedPayloadTemplate: string;
|
|
44
|
+
}
|
|
45
|
+
/** {@link SignatureManifest} as sent on create/update: nullable fields may simply be omitted. */
|
|
46
|
+
export interface SignatureManifestInput {
|
|
47
|
+
algorithm: SignatureAlgorithm;
|
|
48
|
+
encoding: SignatureEncoding;
|
|
49
|
+
headerName: string;
|
|
50
|
+
headerScheme: SignatureHeaderScheme;
|
|
51
|
+
headerPrefix?: Nullable<string>;
|
|
52
|
+
signatureKey?: Nullable<string>;
|
|
53
|
+
timestampHeaderName?: Nullable<string>;
|
|
54
|
+
timestampKey?: Nullable<string>;
|
|
55
|
+
timestampToleranceSeconds?: Nullable<number>;
|
|
56
|
+
signedPayloadTemplate: string;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* How to answer one provider's URL-verification challenge.
|
|
60
|
+
*
|
|
61
|
+
* The fields split by {@link HandshakeKind} — a `QUERY_ECHO` manifest populates the four query
|
|
62
|
+
* parameter names and nulls the rest, a `JSON_ECHO` manifest does the opposite.
|
|
63
|
+
*/
|
|
64
|
+
export interface HandshakeManifest {
|
|
65
|
+
kind: HandshakeKind;
|
|
66
|
+
/** Query parameter holding the value to echo back, e.g. `hub.challenge`. */
|
|
67
|
+
challengeParam: Nullable<string>;
|
|
68
|
+
/** Query parameter holding the token to compare against the endpoint's, e.g. `hub.verify_token`. */
|
|
69
|
+
verifyTokenParam: Nullable<string>;
|
|
70
|
+
/** Query parameter naming the operation, e.g. `hub.mode`. */
|
|
71
|
+
modeParam: Nullable<string>;
|
|
72
|
+
/** Value `modeParam` must hold for this to be a handshake, e.g. `subscribe`. */
|
|
73
|
+
expectedMode: Nullable<string>;
|
|
74
|
+
/** Top-level body field identifying a handshake, e.g. `type`. */
|
|
75
|
+
triggerField: Nullable<string>;
|
|
76
|
+
/** Value `triggerField` must hold, e.g. `url_verification`. */
|
|
77
|
+
triggerValue: Nullable<string>;
|
|
78
|
+
/** Body field holding the value to echo back, e.g. `challenge`. */
|
|
79
|
+
challengeField: Nullable<string>;
|
|
80
|
+
}
|
|
81
|
+
/** {@link HandshakeManifest} as sent on create/update: nullable fields may simply be omitted. */
|
|
82
|
+
export interface HandshakeManifestInput {
|
|
83
|
+
kind: HandshakeKind;
|
|
84
|
+
challengeParam?: Nullable<string>;
|
|
85
|
+
verifyTokenParam?: Nullable<string>;
|
|
86
|
+
modeParam?: Nullable<string>;
|
|
87
|
+
expectedMode?: Nullable<string>;
|
|
88
|
+
triggerField?: Nullable<string>;
|
|
89
|
+
triggerValue?: Nullable<string>;
|
|
90
|
+
challengeField?: Nullable<string>;
|
|
91
|
+
}
|
|
92
|
+
/** One provider on the wire. `GET /api/v1/provider`. */
|
|
93
|
+
export interface Provider {
|
|
94
|
+
/** Null for a built-in — it is not a row and cannot be edited or deleted. */
|
|
95
|
+
id: Nullable<UUID>;
|
|
96
|
+
key: string;
|
|
97
|
+
name: string;
|
|
98
|
+
description: Nullable<string>;
|
|
99
|
+
/** Null when this provider signs nothing. */
|
|
100
|
+
signature: Nullable<SignatureManifest>;
|
|
101
|
+
/** Null when this provider has no URL challenge. */
|
|
102
|
+
handshake: Nullable<HandshakeManifest>;
|
|
103
|
+
/**
|
|
104
|
+
* Ships with Conduit, in code rather than as a seeded row. Override it by creating your own
|
|
105
|
+
* under the same key — resolution checks a tenant's rows first.
|
|
106
|
+
*/
|
|
107
|
+
isBuiltIn: boolean;
|
|
108
|
+
/** Null for a built-in. */
|
|
109
|
+
createdAt: Nullable<IsoDateTime>;
|
|
110
|
+
/** Null for a built-in. */
|
|
111
|
+
updatedAt: Nullable<IsoDateTime>;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Not paginated: the list is the built-ins plus whatever one customer has defined by hand.
|
|
115
|
+
* Wrapped in an object rather than returned as a bare array so a `total` or a cursor can be
|
|
116
|
+
* added later without breaking every client.
|
|
117
|
+
*/
|
|
118
|
+
export interface ProvidersList {
|
|
119
|
+
items: Provider[];
|
|
120
|
+
}
|
|
121
|
+
/** `POST /api/v1/provider`. */
|
|
122
|
+
export interface CreateProviderBody {
|
|
123
|
+
key: string;
|
|
124
|
+
name: string;
|
|
125
|
+
description?: Nullable<string>;
|
|
126
|
+
signature?: Nullable<SignatureManifestInput>;
|
|
127
|
+
handshake?: Nullable<HandshakeManifestInput>;
|
|
128
|
+
}
|
|
129
|
+
/** `PATCH /api/v1/provider/:id`. */
|
|
130
|
+
export interface UpdateProviderBody {
|
|
131
|
+
name?: string;
|
|
132
|
+
description?: Nullable<string>;
|
|
133
|
+
/** Send `null` to stop verifying this provider's signatures. */
|
|
134
|
+
signature?: Nullable<SignatureManifestInput>;
|
|
135
|
+
/** Send `null` to stop answering this provider's challenge. */
|
|
136
|
+
handshake?: Nullable<HandshakeManifestInput>;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=provider.type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.type.d.ts","sourceRoot":"","sources":["../../../../src/api/conduit/provider.type.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SIGNED_PAYLOAD_TIMESTAMP_TOKEN = exports.SIGNED_PAYLOAD_BODY_TOKEN = void 0;
|
|
4
|
+
/** Required in `signedPayloadTemplate`; substituted with the raw request bytes. */
|
|
5
|
+
exports.SIGNED_PAYLOAD_BODY_TOKEN = '{body}';
|
|
6
|
+
/** Optional in `signedPayloadTemplate`; substituted with the timestamp exactly as received. */
|
|
7
|
+
exports.SIGNED_PAYLOAD_TIMESTAMP_TOKEN = '{timestamp}';
|
|
8
|
+
//# sourceMappingURL=provider.type.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.type.js","sourceRoot":"","sources":["../../../../src/api/conduit/provider.type.ts"],"names":[],"mappings":";;;AASA,mFAAmF;AACtE,QAAA,yBAAyB,GAAG,QAAQ,CAAC;AAElD,+FAA+F;AAClF,QAAA,8BAA8B,GAAG,aAAa,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { IsoDateTime } from '../../type/iso-date-time.type.js';
|
|
2
|
+
import type { Nullable } from '../../type/nil.type.js';
|
|
3
|
+
import type { UUID } from '../../type/uuid.type.js';
|
|
4
|
+
/** One replay attempt and whatever came back. */
|
|
5
|
+
export interface Replay {
|
|
6
|
+
id: UUID;
|
|
7
|
+
captureId: UUID;
|
|
8
|
+
targetUrl: string;
|
|
9
|
+
method: string;
|
|
10
|
+
/** The body differed from the capture's, so the original signature no longer verifies. */
|
|
11
|
+
isEdited: boolean;
|
|
12
|
+
/** Null when no response arrived — a timeout, a refused connection. See `errorMessage`. */
|
|
13
|
+
responseStatus: Nullable<number>;
|
|
14
|
+
responseHeaders: Nullable<Record<string, string | string[]>>;
|
|
15
|
+
/** First 64 KB of the response body. */
|
|
16
|
+
responseBodyPreview: Nullable<string>;
|
|
17
|
+
responseBodyTruncated: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Why it failed. **A failed replay is still a 200 from the replay endpoint** — the target
|
|
20
|
+
* being down is the answer you asked for, not an error on Conduit's side.
|
|
21
|
+
*/
|
|
22
|
+
errorMessage: Nullable<string>;
|
|
23
|
+
durationMs: number;
|
|
24
|
+
executedByUserId: Nullable<UUID>;
|
|
25
|
+
createdAt: IsoDateTime;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Unpaginated: one capture accrues a handful of replays while someone fixes a receiver, not
|
|
29
|
+
* thousands.
|
|
30
|
+
*/
|
|
31
|
+
export interface ReplaysList {
|
|
32
|
+
items: Replay[];
|
|
33
|
+
}
|
|
34
|
+
/** `POST /api/v1/capture/:id/replay`. */
|
|
35
|
+
export interface ExecuteReplayBody {
|
|
36
|
+
targetUrl: string;
|
|
37
|
+
/** Defaults to the capture's method. */
|
|
38
|
+
method?: Nullable<string>;
|
|
39
|
+
/** Merged over the captured headers. Signature headers are forwarded deliberately. */
|
|
40
|
+
headers?: Nullable<Record<string, string>>;
|
|
41
|
+
/**
|
|
42
|
+
* Replacement body, base64. Omitting it resends the captured bytes exactly, which is the
|
|
43
|
+
* only way the original signature still verifies — editing necessarily invalidates it, and
|
|
44
|
+
* the resulting replay is flagged `isEdited`.
|
|
45
|
+
*/
|
|
46
|
+
bodyBase64?: Nullable<string>;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=replay.type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replay.type.d.ts","sourceRoot":"","sources":["../../../../src/api/conduit/replay.type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAEpD,iDAAiD;AACjD,MAAM,WAAW,MAAM;IACnB,EAAE,EAAE,IAAI,CAAC;IACT,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IAEf,0FAA0F;IAC1F,QAAQ,EAAE,OAAO,CAAC;IAElB,2FAA2F;IAC3F,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAEjC,eAAe,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC,CAAC;IAE7D,wCAAwC;IACxC,mBAAmB,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAEtC,qBAAqB,EAAE,OAAO,CAAC;IAE/B;;;OAGG;IACH,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAE/B,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;IACjC,SAAS,EAAE,WAAW,CAAC;CAC1B;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IACxB,KAAK,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,yCAAyC;AACzC,MAAM,WAAW,iBAAiB;IAC9B,SAAS,EAAE,MAAM,CAAC;IAElB,wCAAwC;IACxC,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAE1B,sFAAsF;IACtF,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAE3C;;;;OAIG;IACH,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;CACjC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replay.type.js","sourceRoot":"","sources":["../../../../src/api/conduit/replay.type.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hash backing a provider's HMAC.
|
|
3
|
+
*
|
|
4
|
+
* `SHA1` is here because Meta still sends `x-hub-signature` alongside the SHA-256 header and
|
|
5
|
+
* some older integrations only have that one. It is **not** a recommendation — a manifest using
|
|
6
|
+
* it is verifying what the provider actually sends, which is the only useful thing a diagnostic
|
|
7
|
+
* can do. Nothing in Conduit ever *chooses* SHA-1.
|
|
8
|
+
*
|
|
9
|
+
* Values are the strings `node:crypto` expects, so no lookup table stands between the manifest
|
|
10
|
+
* and `createHmac` — one fewer place for a typo to become "signature mismatch".
|
|
11
|
+
*/
|
|
12
|
+
export declare enum SignatureAlgorithm {
|
|
13
|
+
SHA1 = "sha1",
|
|
14
|
+
SHA256 = "sha256",
|
|
15
|
+
SHA512 = "sha512"
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=signature-algorithm.enum.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signature-algorithm.enum.d.ts","sourceRoot":"","sources":["../../../../src/api/conduit/signature-algorithm.enum.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,oBAAY,kBAAkB;IAC1B,IAAI,SAAS;IACb,MAAM,WAAW;IACjB,MAAM,WAAW;CACpB"}
|