@amalgm/core 0.1.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/PURPOSE.md +94 -0
- package/README.md +30 -0
- package/dist/adapters/index.d.ts +13 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +11 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/identity/auth-records.d.ts +147 -0
- package/dist/identity/auth-records.d.ts.map +1 -0
- package/dist/identity/auth-records.js +354 -0
- package/dist/identity/auth-records.js.map +1 -0
- package/dist/identity/ids.d.ts +57 -0
- package/dist/identity/ids.d.ts.map +1 -0
- package/dist/identity/ids.js +80 -0
- package/dist/identity/ids.js.map +1 -0
- package/dist/identity/index.d.ts +14 -0
- package/dist/identity/index.d.ts.map +1 -0
- package/dist/identity/index.js +14 -0
- package/dist/identity/index.js.map +1 -0
- package/dist/identity/labels.d.ts +115 -0
- package/dist/identity/labels.d.ts.map +1 -0
- package/dist/identity/labels.js +154 -0
- package/dist/identity/labels.js.map +1 -0
- package/dist/identity/layout.d.ts +188 -0
- package/dist/identity/layout.d.ts.map +1 -0
- package/dist/identity/layout.js +233 -0
- package/dist/identity/layout.js.map +1 -0
- package/dist/identity/ports.d.ts +31 -0
- package/dist/identity/ports.d.ts.map +1 -0
- package/dist/identity/ports.js +9 -0
- package/dist/identity/ports.js.map +1 -0
- package/dist/identity/product-state.d.ts +49 -0
- package/dist/identity/product-state.d.ts.map +1 -0
- package/dist/identity/product-state.js +55 -0
- package/dist/identity/product-state.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/supervision/app-health.d.ts +148 -0
- package/dist/supervision/app-health.d.ts.map +1 -0
- package/dist/supervision/app-health.js +165 -0
- package/dist/supervision/app-health.js.map +1 -0
- package/dist/supervision/app-restart.d.ts +105 -0
- package/dist/supervision/app-restart.d.ts.map +1 -0
- package/dist/supervision/app-restart.js +97 -0
- package/dist/supervision/app-restart.js.map +1 -0
- package/dist/supervision/health.d.ts +218 -0
- package/dist/supervision/health.d.ts.map +1 -0
- package/dist/supervision/health.js +227 -0
- package/dist/supervision/health.js.map +1 -0
- package/dist/supervision/index.d.ts +17 -0
- package/dist/supervision/index.d.ts.map +1 -0
- package/dist/supervision/index.js +17 -0
- package/dist/supervision/index.js.map +1 -0
- package/dist/supervision/service-registration.d.ts +343 -0
- package/dist/supervision/service-registration.d.ts.map +1 -0
- package/dist/supervision/service-registration.js +543 -0
- package/dist/supervision/service-registration.js.map +1 -0
- package/dist/supervision/update.d.ts +231 -0
- package/dist/supervision/update.d.ts.map +1 -0
- package/dist/supervision/update.js +336 -0
- package/dist/supervision/update.js.map +1 -0
- package/dist/transport/admission.d.ts +235 -0
- package/dist/transport/admission.d.ts.map +1 -0
- package/dist/transport/admission.js +313 -0
- package/dist/transport/admission.js.map +1 -0
- package/dist/transport/auth.d.ts +232 -0
- package/dist/transport/auth.d.ts.map +1 -0
- package/dist/transport/auth.js +266 -0
- package/dist/transport/auth.js.map +1 -0
- package/dist/transport/index.d.ts +21 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.js +21 -0
- package/dist/transport/index.js.map +1 -0
- package/dist/transport/ingress.d.ts +94 -0
- package/dist/transport/ingress.d.ts.map +1 -0
- package/dist/transport/ingress.js +171 -0
- package/dist/transport/ingress.js.map +1 -0
- package/dist/transport/routing.d.ts +235 -0
- package/dist/transport/routing.d.ts.map +1 -0
- package/dist/transport/routing.js +288 -0
- package/dist/transport/routing.js.map +1 -0
- package/dist/transport/shipped-routes.d.ts +21 -0
- package/dist/transport/shipped-routes.d.ts.map +1 -0
- package/dist/transport/shipped-routes.js +53 -0
- package/dist/transport/shipped-routes.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ingress.d.ts","sourceRoot":"","sources":["../../src/transport/ingress.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAM7C,kGAAkG;AAClG,eAAO,MAAM,oBAAoB,QAAkB,CAAC;AAEpD,8HAA8H;AAC9H,eAAO,MAAM,yBAAyB;;;CAG5B,CAAC;AAEX;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,EAAE,WAAW,CAAC,MAAM,CAkBpC,CAAC;AAEZ;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAS7F;AAED,+GAA+G;AAC/G,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAEzC,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,GACb;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,IAAI,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAElE;AAMD,kFAAkF;AAClF,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CAC7C;AAED,0HAA0H;AAC1H,eAAO,MAAM,sBAAsB,4EAIzB,CAAC;AAEX,qGAAqG;AACrG,eAAO,MAAM,aAAa,4EAIhB,CAAC;AAEX,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,GAAG,kBAAkB,GAAG,IAAI,CAiBhF;AAED,uGAAuG;AACvG,MAAM,MAAM,WAAW,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;AAEzF;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,WAAW,EACpB,SAAS,SAAW,GACnB,MAAM,CAER;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAM5G;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,mOAYtB,CAAC;AAEX,kFAAkF;AAClF,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAOtF"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event-rail ingress — the pipe half of the webhook rail. Success at
|
|
3
|
+
* this layer means exactly one thing: the immutable envelope (raw
|
|
4
|
+
* body + allowlisted headers) is durably queued and acknowledged.
|
|
5
|
+
* What a delivery TRIGGERS — the automation fan-out below
|
|
6
|
+
* events/processor.js:119 — is product logic and deliberately not
|
|
7
|
+
* here: the pipe stores and acknowledges the mail, it never reads it
|
|
8
|
+
* (axiom 3). The signature laws live at this layer because verifying
|
|
9
|
+
* WHO sent a payload is admission, not interpretation.
|
|
10
|
+
*
|
|
11
|
+
* Ported from amalgm-mcp/events/ingress.js (receipt contract) and
|
|
12
|
+
* events/matcher.js (signature laws — already pure in the engine).
|
|
13
|
+
*/
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// Receipt contract — events/ingress.js
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
/** ingress.js:12 — the body cap. Counted over raw bytes as they stream in, not after assembly. */
|
|
18
|
+
export const MAX_EVENT_BODY_BYTES = 2 * 1024 * 1024;
|
|
19
|
+
/** The over-limit rejection — ingress.js:50-53 surfaced through the generic error path (:80): status + byte-exact message. */
|
|
20
|
+
export const EVENT_BODY_LIMIT_EXCEEDED = {
|
|
21
|
+
status: 413,
|
|
22
|
+
message: `Event body exceeds ${MAX_EVENT_BODY_BYTES} bytes`,
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* The 17-header storage allowlist — ingress.js:13-31. Everything else
|
|
26
|
+
* is dropped BEFORE the envelope is persisted: the envelope is
|
|
27
|
+
* immutable and replayed, so an unlisted header stored today is a
|
|
28
|
+
* secret leaked forever. The list is exactly: routing identity
|
|
29
|
+
* (x-amalgm-*), each supported sender's event/delivery markers, and
|
|
30
|
+
* every signature/secret header the matcher may need to re-verify.
|
|
31
|
+
*/
|
|
32
|
+
export const STORED_HEADERS = new Set([
|
|
33
|
+
'authorization',
|
|
34
|
+
'content-type',
|
|
35
|
+
'stripe-signature',
|
|
36
|
+
'x-amalgm-delivery-id',
|
|
37
|
+
'x-amalgm-event',
|
|
38
|
+
'x-amalgm-source',
|
|
39
|
+
'x-amalgm-webhook-secret',
|
|
40
|
+
'x-github-delivery',
|
|
41
|
+
'x-github-event',
|
|
42
|
+
'x-gitlab-event',
|
|
43
|
+
'x-gitlab-token',
|
|
44
|
+
'x-hub-signature',
|
|
45
|
+
'x-hub-signature-256',
|
|
46
|
+
'x-linear-event',
|
|
47
|
+
'x-linear-signature',
|
|
48
|
+
'x-webhook-secret',
|
|
49
|
+
'x-webhook-signature',
|
|
50
|
+
]);
|
|
51
|
+
/**
|
|
52
|
+
* ingress.js:33-42 — filter to the allowlist, lowercase the names,
|
|
53
|
+
* join repeated values with ', ', stringify the rest. The result is
|
|
54
|
+
* the envelope's header record — and the flattened shape every
|
|
55
|
+
* signature function below reads.
|
|
56
|
+
*/
|
|
57
|
+
export function storedHeaders(headers) {
|
|
58
|
+
const result = {};
|
|
59
|
+
for (const [key, value] of Object.entries(headers || {})) {
|
|
60
|
+
const normalized = key.toLowerCase();
|
|
61
|
+
if (!STORED_HEADERS.has(normalized))
|
|
62
|
+
continue;
|
|
63
|
+
if (Array.isArray(value))
|
|
64
|
+
result[normalized] = value.join(', ');
|
|
65
|
+
else if (value != null)
|
|
66
|
+
result[normalized] = String(value);
|
|
67
|
+
}
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
/** The receipt acknowledgment — ingress.js:73-78: 202, because acceptance is durable-queued, not processed. */
|
|
71
|
+
export const EVENT_ACCEPTED_STATUS = 202;
|
|
72
|
+
export function eventAcceptedBody(deliveryId, status) {
|
|
73
|
+
return { ok: true, accepted: true, deliveryId, status };
|
|
74
|
+
}
|
|
75
|
+
/** matcher.js:13-17 — HMAC proof headers, in precedence order (generic first, then GitHub's sha256, then legacy sha1). */
|
|
76
|
+
export const HMAC_SIGNATURE_HEADERS = [
|
|
77
|
+
'x-webhook-signature',
|
|
78
|
+
'x-hub-signature-256',
|
|
79
|
+
'x-hub-signature',
|
|
80
|
+
];
|
|
81
|
+
/** matcher.js:19-23 — plain shared-secret headers, in precedence order (ours, generic, GitLab's). */
|
|
82
|
+
export const TOKEN_HEADERS = [
|
|
83
|
+
'x-amalgm-webhook-secret',
|
|
84
|
+
'x-webhook-secret',
|
|
85
|
+
'x-gitlab-token',
|
|
86
|
+
];
|
|
87
|
+
/**
|
|
88
|
+
* The extraction order — matcher.js:28-43: every HMAC header first
|
|
89
|
+
* (an HMAC proof is stronger than a bearer secret, so it must win
|
|
90
|
+
* when a sender supplies both), then `Authorization: Bearer <secret>`
|
|
91
|
+
* (reported under header 'authorization'), then the plain token
|
|
92
|
+
* headers. First PRESENT header wins — an empty value reads as
|
|
93
|
+
* absent. Null when nothing proves anything.
|
|
94
|
+
*/
|
|
95
|
+
export function extractSignature(headers) {
|
|
96
|
+
for (const header of HMAC_SIGNATURE_HEADERS) {
|
|
97
|
+
const value = headers[header];
|
|
98
|
+
if (value)
|
|
99
|
+
return { header, value };
|
|
100
|
+
}
|
|
101
|
+
const authorization = headers['authorization'];
|
|
102
|
+
if (typeof authorization === 'string') {
|
|
103
|
+
const match = authorization.match(/^Bearer\s+(.+)$/i);
|
|
104
|
+
if (match)
|
|
105
|
+
return { header: 'authorization', value: match[1] ?? '' };
|
|
106
|
+
}
|
|
107
|
+
for (const header of TOKEN_HEADERS) {
|
|
108
|
+
const value = headers[header];
|
|
109
|
+
if (value)
|
|
110
|
+
return { header, value };
|
|
111
|
+
}
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* matcher.js:48-50 — the expected proof is `<algorithm>=<hex>`,
|
|
116
|
+
* sha256 unless the caller says otherwise (verification picks sha1
|
|
117
|
+
* only when the presented value announces it — GitHub's legacy
|
|
118
|
+
* x-hub-signature).
|
|
119
|
+
*/
|
|
120
|
+
export function computeSignature(secret, rawBody, hmacHex, algorithm = 'sha256') {
|
|
121
|
+
return `${algorithm}=` + hmacHex(algorithm, secret, rawBody);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* matcher.js:122-128 — the human-readable source label, first
|
|
125
|
+
* recognized marker wins in this order: github → stripe → linear →
|
|
126
|
+
* gitlab → 'external'.
|
|
127
|
+
*/
|
|
128
|
+
export function pickSourceLabel(headers) {
|
|
129
|
+
if (headers['x-github-event'])
|
|
130
|
+
return 'github';
|
|
131
|
+
if (headers['stripe-signature'])
|
|
132
|
+
return 'stripe';
|
|
133
|
+
if (headers['x-linear-event'])
|
|
134
|
+
return 'linear';
|
|
135
|
+
if (headers['x-gitlab-event'])
|
|
136
|
+
return 'gitlab';
|
|
137
|
+
return 'external';
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* The 11 headers worth handing to the agent run context —
|
|
141
|
+
* matcher.js:133-145. Note the deliberate asymmetry with
|
|
142
|
+
* STORED_HEADERS: secrets used only for admission (authorization,
|
|
143
|
+
* x-amalgm-webhook-secret, x-webhook-secret) are stored for
|
|
144
|
+
* re-verification but NOT passed through to agent context — except
|
|
145
|
+
* x-gitlab-token, which GitLab overloads as both auth and event
|
|
146
|
+
* metadata.
|
|
147
|
+
*/
|
|
148
|
+
export const PASSTHROUGH_HEADERS = [
|
|
149
|
+
'x-github-event',
|
|
150
|
+
'x-github-delivery',
|
|
151
|
+
'x-hub-signature-256',
|
|
152
|
+
'x-hub-signature',
|
|
153
|
+
'stripe-signature',
|
|
154
|
+
'x-webhook-signature',
|
|
155
|
+
'content-type',
|
|
156
|
+
'x-linear-event',
|
|
157
|
+
'x-linear-signature',
|
|
158
|
+
'x-gitlab-event',
|
|
159
|
+
'x-gitlab-token',
|
|
160
|
+
];
|
|
161
|
+
/** matcher.js:147-151 — project the passthrough subset, preserving list order. */
|
|
162
|
+
export function collectPassthroughHeaders(headers) {
|
|
163
|
+
const out = {};
|
|
164
|
+
for (const header of PASSTHROUGH_HEADERS) {
|
|
165
|
+
const value = headers[header];
|
|
166
|
+
if (value)
|
|
167
|
+
out[header] = value;
|
|
168
|
+
}
|
|
169
|
+
return out;
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=ingress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ingress.js","sourceRoot":"","sources":["../../src/transport/ingress.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ONE routing table (axiom 4). The engine carries three drifted copies
|
|
3
|
+
* of these laws — local-gateway.js:133-176,627-654 (the gateway's own
|
|
4
|
+
* dispatch), tunnel-events.js:58-89,279-353 and tunnel-chat.js:33-64,
|
|
5
|
+
* 138-194,286-300 (each tunnel's local delivery) — and every incident
|
|
6
|
+
* where a new REST prefix worked over the tunnel but 404'd locally (or
|
|
7
|
+
* vice versa) is that drift cashing out. This module is the one
|
|
8
|
+
* definition; the table CONTENTS are injected product configuration
|
|
9
|
+
* (the kernel routes, it does not know what chat is — axiom 3), with
|
|
10
|
+
* the engine's shipped lists exported from shipped-routes.ts.
|
|
11
|
+
*
|
|
12
|
+
* The pipe never reads the mail: everything here classifies pathnames
|
|
13
|
+
* and port numbers. Nothing inspects a payload.
|
|
14
|
+
*/
|
|
15
|
+
/** The four services a runtime pathname can resolve to. */
|
|
16
|
+
export type RuntimeService = 'gateway' | 'portMonitor' | 'chat' | 'mcp';
|
|
17
|
+
/**
|
|
18
|
+
* The declared-port probe order — tunnel-events.js:315, byte-order
|
|
19
|
+
* preserved (mcp before chat; the sets never overlap in practice, but
|
|
20
|
+
* order is contract until proven dead).
|
|
21
|
+
*/
|
|
22
|
+
export declare const RUNTIME_SERVICES: readonly ["gateway", "portMonitor", "mcp", "chat"];
|
|
23
|
+
/**
|
|
24
|
+
* The one routing table. Buckets are prefix lists; gateway
|
|
25
|
+
* additionally owns a set of exact paths. Contents are product
|
|
26
|
+
* configuration — see shippedRouteTable for the engine's lists.
|
|
27
|
+
*/
|
|
28
|
+
export interface RouteTable {
|
|
29
|
+
readonly gatewayPrefixes: readonly string[];
|
|
30
|
+
readonly gatewayExactPaths: readonly string[];
|
|
31
|
+
readonly portMonitorPrefixes: readonly string[];
|
|
32
|
+
readonly chatPrefixes: readonly string[];
|
|
33
|
+
readonly mcpPrefixes: readonly string[];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The prefix law — tunnel-events.js:279-281, identical in chat and
|
|
37
|
+
* gateway: a prefix claims itself and everything below a '/'
|
|
38
|
+
* boundary. '/chat' claims '/chat' and '/chat/x', never
|
|
39
|
+
* '/chat-payloads' — segment-honest matching is what lets '/chat' and
|
|
40
|
+
* '/chat-payloads' live in different buckets.
|
|
41
|
+
*/
|
|
42
|
+
export declare function prefixMatches(pathname: string, prefix: string): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* tunnel-events.js:283-289 (framePathname) / runtime-auth.js:102-108
|
|
45
|
+
* (pathnameFor) — one copy. Tunnel frame paths and req.url both carry
|
|
46
|
+
* query strings; routing decisions are over the pathname alone.
|
|
47
|
+
* Unparseable input routes as '/'.
|
|
48
|
+
*/
|
|
49
|
+
export declare function pathnameOf(path: string | null | undefined): string;
|
|
50
|
+
/**
|
|
51
|
+
* The classifier — canonical order is the TUNNEL order
|
|
52
|
+
* (tunnel-events.js:291-300): gateway (exact paths first, then
|
|
53
|
+
* prefixes) → portMonitor → chat → mcp → null.
|
|
54
|
+
*
|
|
55
|
+
* The engine's gateway checks chat → mcp → portMonitor instead
|
|
56
|
+
* (local-gateway.js:627-647, after handling its own routes). The two
|
|
57
|
+
* orders are currently indistinguishable because no prefix in one
|
|
58
|
+
* bucket sits under a prefix in another — no pathname can match two
|
|
59
|
+
* buckets, so match order never decides a winner. That is an
|
|
60
|
+
* assumption about table CONTENTS, so assertNoBucketCollisions below
|
|
61
|
+
* makes it executable: run it over any injected table and the
|
|
62
|
+
* "order doesn't matter" claim is proven, not remembered.
|
|
63
|
+
*/
|
|
64
|
+
export declare function serviceForRuntimePath(pathname: string, table: RouteTable): RuntimeService | null;
|
|
65
|
+
/**
|
|
66
|
+
* The executable form of the order-indistinguishability assumption:
|
|
67
|
+
* two prefixes from different buckets may never claim the same
|
|
68
|
+
* pathname. Prefix a and prefix b share a claimable pathname exactly
|
|
69
|
+
* when one prefix-matches the other (then the deeper prefix itself is
|
|
70
|
+
* such a pathname), so that is the whole check. Gateway exact paths
|
|
71
|
+
* are also checked against the other buckets' prefixes: both shipped
|
|
72
|
+
* orders test gateway first, and this keeps even that ordering
|
|
73
|
+
* non-load-bearing.
|
|
74
|
+
*/
|
|
75
|
+
export declare function assertNoBucketCollisions(table: RouteTable): void;
|
|
76
|
+
/**
|
|
77
|
+
* The gateway's prefix-strip law — local-gateway.js:637-645: before
|
|
78
|
+
* proxying to the port monitor it strips '/port-monitor', else
|
|
79
|
+
* '/ports' (first match wins, checked in this order), but deliberately
|
|
80
|
+
* NOT '/api/ports' — that one is the port monitor's own native prefix
|
|
81
|
+
* and forwards verbatim. '/chat' and '/mcp'-bucket paths always
|
|
82
|
+
* forward verbatim (stripPrefix '').
|
|
83
|
+
*/
|
|
84
|
+
export declare const PORT_MONITOR_STRIP_PREFIXES: readonly ["/port-monitor", "/ports"];
|
|
85
|
+
export interface ForwardTarget {
|
|
86
|
+
readonly service: RuntimeService;
|
|
87
|
+
readonly forwardPath: string;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Classify a pathname and compute the path to forward upstream —
|
|
91
|
+
* local-gateway.js:627-647 (serviceForPath) + :687-692 (proxiedPath,
|
|
92
|
+
* slice then `|| '/'`), generalized over the injected table. Pathname
|
|
93
|
+
* in, pathname out: the host re-attaches the query string, as
|
|
94
|
+
* proxiedPath does.
|
|
95
|
+
*
|
|
96
|
+
* DRIFT, documented as a wound the cutover closes: the tunnels
|
|
97
|
+
* forward frame paths VERBATIM to the resolved service
|
|
98
|
+
* (tunnel-events.js:678-684 passes frame.path straight to
|
|
99
|
+
* http.request), so '/ports/x' reaches the port monitor as '/ports/x'
|
|
100
|
+
* over a tunnel but as '/x' through the gateway. The gateway behavior
|
|
101
|
+
* ported here is canonical; when the tunnels adopt this function the
|
|
102
|
+
* two paths converge.
|
|
103
|
+
*
|
|
104
|
+
* Two deliberate departures from the engine's serviceForPath, both
|
|
105
|
+
* because this is the whole table rather than the gateway's slice of
|
|
106
|
+
* it: gateway-bucket paths return {service:'gateway'} instead of null
|
|
107
|
+
* (the engine returns null there because the gateway has already
|
|
108
|
+
* handled its own routes by that line), and the strip test uses the
|
|
109
|
+
* classified pathname, where the engine's raw startsWith is
|
|
110
|
+
* indistinguishable ('/portsfoo' never classifies as portMonitor).
|
|
111
|
+
*/
|
|
112
|
+
export declare function forwardPathForService(pathname: string, table: RouteTable): ForwardTarget | null;
|
|
113
|
+
/** tunnel-events.js:274-277 — a port is an integer in (0, 65535], or it is nothing. */
|
|
114
|
+
export declare function validPort(value: unknown): number | null;
|
|
115
|
+
/** A fully resolved port per service (defaults come from the host's runtime manifest). */
|
|
116
|
+
export interface RuntimePorts {
|
|
117
|
+
readonly gateway: number;
|
|
118
|
+
readonly portMonitor: number;
|
|
119
|
+
readonly mcp: number;
|
|
120
|
+
readonly chat: number;
|
|
121
|
+
}
|
|
122
|
+
/** Possibly-partial ports as read from a runtime-state file of unknown age. */
|
|
123
|
+
export type RuntimePortsLike = {
|
|
124
|
+
readonly [service in RuntimeService]?: number | null | undefined;
|
|
125
|
+
};
|
|
126
|
+
/** The subset of runtime-state.json the port mapping reads. */
|
|
127
|
+
export interface RuntimeStateLike {
|
|
128
|
+
readonly gateway_port?: unknown;
|
|
129
|
+
readonly ports?: {
|
|
130
|
+
readonly gateway?: unknown;
|
|
131
|
+
readonly port_monitor?: unknown;
|
|
132
|
+
readonly amalgm_mcp?: unknown;
|
|
133
|
+
readonly chat_server?: unknown;
|
|
134
|
+
} | null;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* The runtime-state port mapping — the tunnels' `readRuntimePorts`
|
|
138
|
+
* (tunnel-events.js:255-272, byte-identical in tunnel-chat.js:114-131;
|
|
139
|
+
* the engine name is kept — the manifest's declaration-driven
|
|
140
|
+
* `runtimePortsFromState` is a different law and lives in
|
|
141
|
+
* `supervision/service-registration.ts`). Top-level `gateway_port` wins
|
|
142
|
+
* over `ports.gateway` (older writers only wrote the former); the
|
|
143
|
+
* other services live only under `ports.*` in snake_case. `Number(x)
|
|
144
|
+
* || fallback` verbatim: absent, unparseable, and zero all fall back.
|
|
145
|
+
* The engine's catch-branch (unreadable file) is the host's: pass no
|
|
146
|
+
* state and the fallbacks come through whole.
|
|
147
|
+
*/
|
|
148
|
+
export declare function readRuntimePorts(state: RuntimeStateLike | null | undefined, fallbacks: RuntimePorts): RuntimePorts;
|
|
149
|
+
/**
|
|
150
|
+
* The mirror-write shape — local-gateway.js:395-402: what the gateway
|
|
151
|
+
* writes is exactly what readRuntimePorts reads, top-level
|
|
152
|
+
* `gateway_port` doubled into `ports.gateway` included.
|
|
153
|
+
*/
|
|
154
|
+
export declare function runtimeStatePortsPatch(ports: RuntimePorts): {
|
|
155
|
+
gateway_port: number;
|
|
156
|
+
ports: {
|
|
157
|
+
gateway: number;
|
|
158
|
+
port_monitor: number;
|
|
159
|
+
amalgm_mcp: number;
|
|
160
|
+
chat_server: number;
|
|
161
|
+
};
|
|
162
|
+
};
|
|
163
|
+
/** tunnel-events.js:302-308 — which service does a well-known DEFAULT port imply? Checked against defaults, never live ports. */
|
|
164
|
+
export declare function defaultServiceForPort(port: number, defaults: RuntimePorts): RuntimeService | null;
|
|
165
|
+
/** tunnel-events.js:310-312 — live port if valid, else the default; null when both are broken. */
|
|
166
|
+
export declare function runtimePortForService(runtimePorts: RuntimePortsLike, defaults: RuntimePorts, service: RuntimeService): number | null;
|
|
167
|
+
/** tunnel-events.js:314-316 — is this port one the live runtime actually declared? Order-sensitive over RUNTIME_SERVICES. */
|
|
168
|
+
export declare function isDeclaredRuntimePort(port: number, runtimePorts: RuntimePortsLike): boolean;
|
|
169
|
+
/**
|
|
170
|
+
* The full set of ports a tunnel frame may target —
|
|
171
|
+
* tunnel-events.js:318-326: every resolvable service port plus, on
|
|
172
|
+
* the events tunnel, every advertised app-route port. DRIFT:
|
|
173
|
+
* tunnel-chat.js:177-184 omits the app ports (chat frames never
|
|
174
|
+
* target apps); that divergence is this parameter, not a second copy
|
|
175
|
+
* — pass no appRoutePorts and you have the chat version.
|
|
176
|
+
*/
|
|
177
|
+
export declare function allowedTargetPorts(runtimePorts: RuntimePortsLike, defaults: RuntimePorts, appRoutePorts?: Iterable<number>): Set<number>;
|
|
178
|
+
/** The wire fields target resolution reads, named as the tunnel frame names them. */
|
|
179
|
+
export interface TunnelFrameTarget {
|
|
180
|
+
readonly target_port?: unknown;
|
|
181
|
+
readonly path?: string | null;
|
|
182
|
+
}
|
|
183
|
+
export interface ResolveTargetPortOptions {
|
|
184
|
+
readonly runtimePorts: RuntimePortsLike;
|
|
185
|
+
readonly defaults: RuntimePorts;
|
|
186
|
+
readonly table: RouteTable;
|
|
187
|
+
/**
|
|
188
|
+
* 'mcp' for the events tunnel, 'chat' for the chat tunnel. The
|
|
189
|
+
* events engine derives this as `fallbackPort === defaultTargetPort()
|
|
190
|
+
* ? 'mcp' : defaultServiceForPort(fallbackPort)` (tunnel-events.js:343)
|
|
191
|
+
* — but no caller ever passes a fallbackPort, so the derivation is
|
|
192
|
+
* always 'mcp'; the chat tunnel hardcodes 'chat'
|
|
193
|
+
* (tunnel-chat.js:291). Injected here instead of re-porting a dead
|
|
194
|
+
* parameter.
|
|
195
|
+
*/
|
|
196
|
+
readonly fallbackService: RuntimeService;
|
|
197
|
+
/** App-route ports (events tunnel only) — see allowedTargetPorts. */
|
|
198
|
+
readonly appRoutePorts?: Iterable<number>;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* The target-port law — canonical form is tunnel-events.js:338-353
|
|
202
|
+
* (tunnel-chat.js:286-300 is the same law with fallbackService
|
|
203
|
+
* 'chat' and no app ports):
|
|
204
|
+
* 1. a requested port the live runtime declared is honored verbatim;
|
|
205
|
+
* 2. otherwise the frame's PATH picks the service — but only when no
|
|
206
|
+
* port was requested, or the requested port is a well-known
|
|
207
|
+
* default (a stale peer aiming at where a service used to live:
|
|
208
|
+
* the path outranks the stale number and both remap to the live
|
|
209
|
+
* port);
|
|
210
|
+
* 3. a requested port that names neither a declared port, a default,
|
|
211
|
+
* nor a routable path must be in the allowed set (app routes) or
|
|
212
|
+
* it resolves to null — and null is the denial contract below.
|
|
213
|
+
*/
|
|
214
|
+
export declare function resolveTargetPort(frame: TunnelFrameTarget, options: ResolveTargetPortOptions): number | null;
|
|
215
|
+
/** Tunnel res-frame denial — tunnel-events.js:668-674 (and stream/ws variants at :710-715,:778-779). */
|
|
216
|
+
export declare const TARGET_PORT_DENIED_STATUS = 403;
|
|
217
|
+
export declare const TARGET_PORT_DENIED_MESSAGE = "Target port is not allowed";
|
|
218
|
+
/** The frozen body bytes of the non-stream denial (JSON.stringify({ error: ... }) at :673). */
|
|
219
|
+
export declare const TARGET_PORT_DENIED_BODY = "{\"error\":\"Target port is not allowed\"}";
|
|
220
|
+
/** WebSocket denial — tunnel-events.js:779: policy-violation close with the same reason. */
|
|
221
|
+
export declare const WS_CLOSE_TARGET_PORT_DENIED: {
|
|
222
|
+
readonly code: 1008;
|
|
223
|
+
readonly reason: "Target port is not allowed";
|
|
224
|
+
};
|
|
225
|
+
/** Gateway preview denial — local-gateway.js:675. */
|
|
226
|
+
export declare function previewPortDeniedError(port: number): {
|
|
227
|
+
status: 403;
|
|
228
|
+
message: string;
|
|
229
|
+
};
|
|
230
|
+
/** Gateway app denial — local-gateway.js:662. */
|
|
231
|
+
export declare function appNotRoutableError(appRef: string): {
|
|
232
|
+
status: 404;
|
|
233
|
+
message: string;
|
|
234
|
+
};
|
|
235
|
+
//# sourceMappingURL=routing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routing.d.ts","sourceRoot":"","sources":["../../src/transport/routing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,2DAA2D;AAC3D,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,aAAa,GAAG,MAAM,GAAG,KAAK,CAAC;AAExE;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,oDAAqD,CAAC;AAEnF;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,QAAQ,CAAC,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9C,QAAQ,CAAC,mBAAmB,EAAE,SAAS,MAAM,EAAE,CAAC;IAChD,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;CACzC;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAEvE;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAMlE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,cAAc,GAAG,IAAI,CAWhG;AAED;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAgChE;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,sCAAuC,CAAC;AAEhF,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,aAAa,GAAG,IAAI,CAQ/F;AAMD,uFAAuF;AACvF,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAGvD;AAED,0FAA0F;AAC1F,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,+EAA+E;AAC/E,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,EAAE,OAAO,IAAI,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS;CACjE,CAAC;AAEF,+DAA+D;AAC/D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,KAAK,CAAC,EAAE;QACf,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;QAC3B,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;QAChC,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;QAC9B,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;KAChC,GAAG,IAAI,CAAC;CACV;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,gBAAgB,GAAG,IAAI,GAAG,SAAS,EAC1C,SAAS,EAAE,YAAY,GACtB,YAAY,CAOd;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,YAAY,GAAG;IAC3D,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3F,CAUA;AAED,iIAAiI;AACjI,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,cAAc,GAAG,IAAI,CAMjG;AAED,kGAAkG;AAClG,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,gBAAgB,EAC9B,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE,cAAc,GACtB,MAAM,GAAG,IAAI,CAEf;AAED,6HAA6H;AAC7H,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,gBAAgB,GAAG,OAAO,CAE3F;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,gBAAgB,EAC9B,QAAQ,EAAE,YAAY,EACtB,aAAa,GAAE,QAAQ,CAAC,MAAM,CAAM,GACnC,GAAG,CAAC,MAAM,CAAC,CAQb;AAED,qFAAqF;AACrF,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,YAAY,EAAE,gBAAgB,CAAC;IACxC,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B;;;;;;;;OAQG;IACH,QAAQ,CAAC,eAAe,EAAE,cAAc,CAAC;IACzC,qEAAqE;IACrE,QAAQ,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;CAC3C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,iBAAiB,EACxB,OAAO,EAAE,wBAAwB,GAChC,MAAM,GAAG,IAAI,CAkBf;AAMD,wGAAwG;AACxG,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAC7C,eAAO,MAAM,0BAA0B,+BAA+B,CAAC;AACvE,+FAA+F;AAC/F,eAAO,MAAM,uBAAuB,+CAA2C,CAAC;AAChF,4FAA4F;AAC5F,eAAO,MAAM,2BAA2B;;;CAA8D,CAAC;AAEvG,qDAAqD;AACrD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,GAAG,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAErF;AAED,iDAAiD;AACjD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,GAAG,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAEpF"}
|