@webpieces/core-util 0.4.760 → 0.4.762
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/ContextKey.d.ts +3 -3
- package/src/ContextKey.js +3 -3
- package/src/ContextKey.js.map +1 -1
- package/src/http/ContextMgr.d.ts +2 -2
- package/src/http/ContextMgr.js +2 -2
- package/src/http/ContextMgr.js.map +1 -1
- package/src/http/DestinationTrust.d.ts +5 -5
- package/src/http/DestinationTrust.js +8 -8
- package/src/http/DestinationTrust.js.map +1 -1
- package/src/http/RouteMetadata.d.ts +1 -1
- package/src/http/RouteMetadata.js +1 -1
- package/src/http/RouteMetadata.js.map +1 -1
- package/src/http/RuntimeLocality.d.ts +3 -3
- package/src/http/RuntimeLocality.js +1 -1
- package/src/http/RuntimeLocality.js.map +1 -1
- package/src/http/Secrets.d.ts +2 -2
- package/src/http/Secrets.js +2 -2
- package/src/http/Secrets.js.map +1 -1
- package/src/http/WebpiecesCoreHeaders.d.ts +2 -2
- package/src/http/WebpiecesCoreHeaders.js +22 -7
- package/src/http/WebpiecesCoreHeaders.js.map +1 -1
- package/src/http/{AuthApiKeyCompileAssertions.d.ts → WpAuthApiKeyCompileAssertions.d.ts} +4 -4
- package/src/http/{AuthApiKeyCompileAssertions.js → WpAuthApiKeyCompileAssertions.js} +25 -11
- package/src/http/WpAuthApiKeyCompileAssertions.js.map +1 -0
- package/src/http/{AuthJwtCompileAssertions.d.ts → WpAuthJwtCompileAssertions.d.ts} +2 -0
- package/src/http/{AuthJwtCompileAssertions.js → WpAuthJwtCompileAssertions.js} +19 -12
- package/src/http/WpAuthJwtCompileAssertions.js.map +1 -0
- package/src/http/auth-mode.d.ts +8 -8
- package/src/http/auth-mode.js +1 -1
- package/src/http/auth-mode.js.map +1 -1
- package/src/http/decorators.d.ts +47 -44
- package/src/http/decorators.js +95 -81
- package/src/http/decorators.js.map +1 -1
- package/src/index.d.ts +3 -1
- package/src/index.js +23 -12
- package/src/index.js.map +1 -1
- package/src/ipc/IpcDecorators.d.ts +23 -0
- package/src/ipc/IpcDecorators.js +104 -0
- package/src/ipc/IpcDecorators.js.map +1 -0
- package/src/ipc/IpcIdentity.d.ts +3 -0
- package/src/ipc/IpcIdentity.js +14 -0
- package/src/ipc/IpcIdentity.js.map +1 -0
- package/src/ipc/IpcProtocol.js +6 -6
- package/src/ipc/IpcProtocol.js.map +1 -1
- package/src/ipc/index.d.ts +4 -2
- package/src/ipc/index.js +16 -5
- package/src/ipc/index.js.map +1 -1
- package/src/http/AuthApiKeyCompileAssertions.js.map +0 -1
- package/src/http/AuthJwtCompileAssertions.js.map +0 -1
- package/src/ipc/IpcCompileAssertions.d.ts +0 -4
- package/src/ipc/IpcCompileAssertions.js +0 -39
- package/src/ipc/IpcCompileAssertions.js.map +0 -1
- package/src/ipc/IpcContract.d.ts +0 -32
- package/src/ipc/IpcContract.js +0 -65
- package/src/ipc/IpcContract.js.map +0 -1
package/src/http/decorators.d.ts
CHANGED
|
@@ -10,6 +10,8 @@ export declare const METADATA_KEYS: {
|
|
|
10
10
|
API_PATH: string;
|
|
11
11
|
ENDPOINTS: string;
|
|
12
12
|
AUTH_META: string;
|
|
13
|
+
/** Method names carrying one of the canonical authorization decorators. */
|
|
14
|
+
AUTH_METHODS: string;
|
|
13
15
|
/** 'rpc' (default, sync request/response) vs 'pubsub' (fire-and-forget cloud task). */
|
|
14
16
|
API_KIND: string;
|
|
15
17
|
/** Per-method Cloud Tasks queue-name override (set via @Queue). */
|
|
@@ -54,14 +56,14 @@ export interface EndpointOptions {
|
|
|
54
56
|
formPost?: boolean;
|
|
55
57
|
/**
|
|
56
58
|
* RETAIN the verbatim request bytes + the absolute url the sender addressed, so an
|
|
57
|
-
* {@link
|
|
59
|
+
* {@link WpAuthWebhook} hook can verify a vendor signature over them (see `RawRequest`).
|
|
58
60
|
*
|
|
59
61
|
* Opt-in PER ENDPOINT, sitting beside `formPost` and for the same reason: the cost lands on the
|
|
60
62
|
* handful of webhook routes rather than on every request in the process. It is retention, not
|
|
61
63
|
* new buffering — the express adapter already accumulates the whole body, it simply threw it
|
|
62
64
|
* away once it had parsed a DTO.
|
|
63
65
|
*
|
|
64
|
-
* REQUIRED by `@
|
|
66
|
+
* REQUIRED by `@WpAuthWebhook`, checked at wiring time (see
|
|
65
67
|
* {@link assertEveryWebhookEndpointRetainsRawBody}) rather than left to fail as a 401 in
|
|
66
68
|
* production: a hook with nothing to verify is a misconfiguration, not a bad request.
|
|
67
69
|
*
|
|
@@ -86,9 +88,9 @@ export interface ExternalEndpointOptions extends EndpointOptions {
|
|
|
86
88
|
*
|
|
87
89
|
* Usage:
|
|
88
90
|
* ```typescript
|
|
89
|
-
* @AuthJwt({ roles: ['admin'] })
|
|
90
91
|
* @ApiPath('/api/save')
|
|
91
92
|
* abstract class SaveApi {
|
|
93
|
+
* @WpAuthJwt({ roles: ['admin'] })
|
|
92
94
|
* @Endpoint('/item', 'rpc')
|
|
93
95
|
* save(request: SaveRequest): Promise<SaveResponse> { ... }
|
|
94
96
|
* }
|
|
@@ -160,23 +162,24 @@ export declare function MaskLog(fields: Record<string, MaskMode>): MethodDecorat
|
|
|
160
162
|
*/
|
|
161
163
|
export declare function getMaskSpec(apiClass: Function, methodName: string): MaskSpec | undefined;
|
|
162
164
|
/**
|
|
163
|
-
* @
|
|
165
|
+
* @WpAuthPublic(reason) - endpoint intentionally requires no authentication.
|
|
166
|
+
* The non-empty reason makes anonymous exposure an explicit review decision.
|
|
164
167
|
*/
|
|
165
|
-
export declare function
|
|
168
|
+
export declare function WpAuthPublic(reason: string): MethodDecorator;
|
|
166
169
|
/**
|
|
167
|
-
* @
|
|
170
|
+
* @WpAuthJwt(requirement) - THE user-facing JWT decorator, covering the whole user-JWT axis: the
|
|
168
171
|
* compiler-enforced role decision ({@link JwtRoles}) plus app-defined fields ({@link JwtRequirement}).
|
|
169
172
|
*
|
|
170
173
|
* ```typescript
|
|
171
|
-
* @
|
|
172
|
-
* @
|
|
174
|
+
* @WpAuthJwt({ roles: ['admin', 'editor'] }) // any-of
|
|
175
|
+
* @WpAuthJwt({ allRolesAllowed: true, inOrg: true }) // wide + an app rule enforced by authorizeJwt
|
|
173
176
|
* ```
|
|
174
177
|
*
|
|
175
178
|
* It absorbed the former `@Auth(requirement)` — same argument, same AuthMode, so two spellings of one
|
|
176
|
-
* decision. One decorator per credential kind now: `@
|
|
177
|
-
* `@
|
|
179
|
+
* decision. One decorator per credential kind now: `@WpAuthPublic` / `@WpAuthJwt` / `@WpAuthOidc` /
|
|
180
|
+
* `@WpAuthSharedSecret` / `@WpAuthLocalOnly`.
|
|
178
181
|
*/
|
|
179
|
-
export declare function
|
|
182
|
+
export declare function WpAuthJwt(requirement: JwtRequirement): MethodDecorator;
|
|
180
183
|
/**
|
|
181
184
|
* The roles an endpoint accepts, or [] when it accepts every authenticated user. The ONE reader of
|
|
182
185
|
* the {@link JwtRoles} union, so no caller has to re-derive "does absent mean wide?" — a question
|
|
@@ -184,38 +187,38 @@ export declare function AuthJwt(requirement: JwtRequirement): ClassDecorator & M
|
|
|
184
187
|
*/
|
|
185
188
|
export declare function rolesRequired(requirement: JwtRequirement): readonly string[];
|
|
186
189
|
/**
|
|
187
|
-
* @
|
|
190
|
+
* @WpAuthOidc(...callers) - Google OIDC service-to-service auth (Cloud Tasks delivery / cross-service
|
|
188
191
|
* RPC). `callers` is an OPTIONAL app-level allow-list of caller service accounts.
|
|
189
192
|
*
|
|
190
193
|
* NO args = TRUST THE EDGE: accept any genuine Google-signed OIDC caller, because a PRIVATE Cloud
|
|
191
194
|
* Run service's edge already gates WHO via `run.invoker` IAM (managed in terraform — one source of
|
|
192
195
|
* truth, no hand-synced list in code). If the service is actually PUBLIC, the verifier logs a loud
|
|
193
|
-
* warning (it can't be the gate then). Pass explicit SAs (`@
|
|
196
|
+
* warning (it can't be the gate then). Pass explicit SAs (`@WpAuthOidc('svc-a')`) only when you want
|
|
194
197
|
* an additional app-level allow-list as defense-in-depth.
|
|
195
198
|
*/
|
|
196
|
-
export declare function
|
|
199
|
+
export declare function WpAuthOidc(...callers: string[]): MethodDecorator;
|
|
197
200
|
/**
|
|
198
|
-
* @
|
|
201
|
+
* @WpAuthSharedSecret(key) - constant-time compare of an inbound header against the secret bound for
|
|
199
202
|
* `key`. `key` is a LOOKUP KEY (not an env var): the server looks up its accepted {@link SharedSecrets}
|
|
200
203
|
* by this key, and each client looks up the value it sends by the SAME key (see {@link Secrets}).
|
|
201
204
|
* For internal callers that cannot mint OIDC tokens.
|
|
202
205
|
*/
|
|
203
|
-
export declare function
|
|
206
|
+
export declare function WpAuthSharedSecret(key: string): MethodDecorator;
|
|
204
207
|
/**
|
|
205
|
-
* @
|
|
208
|
+
* @WpAuthWebhook(name) - an OUTSIDE vendor signed this request in its OWN scheme; the app's bound
|
|
206
209
|
* `WebhookAuthCallback` proves it. THE mode for every signed inbound webhook — Sentry, GitHub, Stripe, Slack,
|
|
207
210
|
* Twilio — none of which fits the other kinds: no vendor mints Google OIDC tokens, and none sends its
|
|
208
|
-
* secret (they all send a DERIVATION over the request), so `@
|
|
211
|
+
* secret (they all send a DERIVATION over the request), so `@WpAuthPublic` was the only reachable posture
|
|
209
212
|
* and `calledBy: 'sentry'` stayed a claim rather than a fact.
|
|
210
213
|
*
|
|
211
214
|
* ```typescript
|
|
212
|
-
* @
|
|
215
|
+
* @WpAuthWebhook('sentry')
|
|
213
216
|
* @Endpoint('/hook/sentry/issue', 'external', { calledBy: 'sentry', rawBody: true })
|
|
214
217
|
* abstract notify(request: SentryIssueHook): Promise<HookAck>;
|
|
215
218
|
* ```
|
|
216
219
|
*
|
|
217
220
|
* `name` is a bare STRING resolved through DI in the server's container, exactly as
|
|
218
|
-
* `@
|
|
221
|
+
* `@WpAuthOidc('gmail-push')` already is — never a function reference. An api contract is level 0: a
|
|
219
222
|
* direct reference to a verifier would invert the dependency graph and drag a vendor SDK into the
|
|
220
223
|
* browser bundle that imports the same contract.
|
|
221
224
|
*
|
|
@@ -227,18 +230,18 @@ export declare function AuthSharedSecret(key: string): ClassDecorator & MethodDe
|
|
|
227
230
|
* call the vendor's own library — hence the REQUIRED `{ rawBody: true }` (see
|
|
228
231
|
* {@link EndpointOptions.rawBody}), which is checked at wiring time.
|
|
229
232
|
*
|
|
230
|
-
* FAILS CLOSED: with no `WebhookAuthCallback` bound, every `@
|
|
233
|
+
* FAILS CLOSED: with no `WebhookAuthCallback` bound, every `@WpAuthWebhook` endpoint 401s, matching `JwtHook`.
|
|
231
234
|
* Silently allowing an unverified webhook is the one default that must not exist.
|
|
232
235
|
*/
|
|
233
|
-
export declare function
|
|
236
|
+
export declare function WpAuthWebhook(name: string): MethodDecorator;
|
|
234
237
|
/**
|
|
235
|
-
* @
|
|
238
|
+
* @WpAuthApiKey(regime, credentials) - a CUSTOMER holds the credential. The app's bound `ApiKeyHook`
|
|
236
239
|
* authenticates the inbound request against its own datastore and returns the `ContextTuple` entries
|
|
237
240
|
* the framework seeds into `RequestContext`. THE mode for a partner-facing contract consumed by other
|
|
238
241
|
* companies' codebases (POS vendors, back-office platforms, ETL pipelines).
|
|
239
242
|
*
|
|
240
243
|
* ```typescript
|
|
241
|
-
* @
|
|
244
|
+
* @WpAuthApiKey('onetablet-partner', [
|
|
242
245
|
* { in: 'header', name: 'x-api-key', description: 'The key issued to your integration.' },
|
|
243
246
|
* { in: 'header', name: 'x-organization-id', description: 'Which of your organizations to act on.' },
|
|
244
247
|
* ])
|
|
@@ -247,7 +250,7 @@ export declare function AuthWebhook(name: string): ClassDecorator & MethodDecora
|
|
|
247
250
|
* ```
|
|
248
251
|
*
|
|
249
252
|
* `regime` is a bare STRING selecting WHICH key regime this route belongs to, exactly as
|
|
250
|
-
* `@
|
|
253
|
+
* `@WpAuthSharedSecret(key)` and `@WpAuthWebhook(vendor)` already are — one hook serves several regimes,
|
|
251
254
|
* and an api contract is level 0, so it never references a verifier directly.
|
|
252
255
|
*
|
|
253
256
|
* `credentials` DECLARES where the credential rides ({@link ApiKeyCredential}), so a spec generator
|
|
@@ -265,10 +268,10 @@ export declare function AuthWebhook(name: string): ClassDecorator & MethodDecora
|
|
|
265
268
|
* exists to remove. That is a compile error, not a runtime throw (see {@link JwtRoles}'s non-empty
|
|
266
269
|
* tuple, the same device for the same reason).
|
|
267
270
|
*
|
|
268
|
-
* WHY IT IS NOT `@
|
|
271
|
+
* WHY IT IS NOT `@WpAuthSharedSecret`. Shared-secret declares that AN INTERNAL SERVICE is on the other
|
|
269
272
|
* end, so the framework BELIEVES the trusted context headers that caller forwarded (see
|
|
270
273
|
* `DestinationTrust.forAuthMode` and `AuthFilter.verifiesCaller`). A customer is not an internal
|
|
271
|
-
* service: declaring a partner endpoint `@
|
|
274
|
+
* service: declaring a partner endpoint `@WpAuthSharedSecret` would let that partner assert someone
|
|
272
275
|
* else's org id on the wire and have it admitted — a privilege escalation. `apikey` therefore sits
|
|
273
276
|
* with `jwt` on the caller-NOT-verified side, where an inbound trusted header is admitted only when
|
|
274
277
|
* the hook independently derived the SAME value.
|
|
@@ -280,16 +283,17 @@ export declare function AuthWebhook(name: string): ClassDecorator & MethodDecora
|
|
|
280
283
|
* PAIR. `credentials` does NOT change that: the framework reads no header from it and performs no
|
|
281
284
|
* extraction. It is DECLARATION for readers of the contract, and enforcement stays entirely the hook's.
|
|
282
285
|
*
|
|
283
|
-
* FAILS CLOSED: with no `ApiKeyHook` bound, every `@
|
|
286
|
+
* FAILS CLOSED: with no `ApiKeyHook` bound, every `@WpAuthApiKey` endpoint 401s, matching `JwtHook` and
|
|
284
287
|
* `WebhookAuthCallback`.
|
|
285
288
|
*/
|
|
286
|
-
export declare function
|
|
289
|
+
export declare function WpAuthApiKey(regime: string, credentials: ApiKeyCredentials): MethodDecorator;
|
|
287
290
|
/**
|
|
288
|
-
* @
|
|
289
|
-
* registered as a route at all, and if it is somehow reached it 404s.
|
|
291
|
+
* @WpAuthLocalOnly() - this endpoint exists ONLY on a developer's machine. Off-local it is not
|
|
292
|
+
* registered as a route at all, and if it is somehow reached it 404s. Method-only, like every
|
|
293
|
+
* authorization decorator, so every endpoint's posture is visible at the method.
|
|
290
294
|
*
|
|
291
295
|
* ```typescript
|
|
292
|
-
* @
|
|
296
|
+
* @WpAuthLocalOnly()
|
|
293
297
|
* @Endpoint('/logs', 'rpc')
|
|
294
298
|
* sendBatch(request: SendLogBatchRequest): Promise<SendLogBatchResponse> { ... }
|
|
295
299
|
* ```
|
|
@@ -298,11 +302,11 @@ export declare function AuthApiKey(regime: string, credentials: ApiKeyCredential
|
|
|
298
302
|
* sync by a comment: a route module that registered the route only locally, PLUS a
|
|
299
303
|
* `if (env !== 'local') throw new ForbiddenError(...)` at the top of the handler. Neither half
|
|
300
304
|
* was visible on the CONTRACT, so nothing reading the api — a human, a generated client, or an
|
|
301
|
-
* agent — could tell this endpoint from a `@
|
|
305
|
+
* agent — could tell this endpoint from a `@WpAuthPublic` one. Both halves are the framework's job now,
|
|
302
306
|
* driven by this ONE declaration on the contract, which is where every other "who may call this"
|
|
303
307
|
* fact already lives.
|
|
304
308
|
*
|
|
305
|
-
* It is DELIBERATELY a peer of @
|
|
309
|
+
* It is DELIBERATELY a peer of @WpAuthPublic / @WpAuthJwt / @WpAuthOidc / @WpAuthSharedSecret / @WpAuthApiKey rather than an
|
|
306
310
|
* option on one of them: one decorator per credential kind, and "local-only" is a different kind of
|
|
307
311
|
* gate — it authenticates nobody, it excludes an entire environment.
|
|
308
312
|
*
|
|
@@ -310,7 +314,7 @@ export declare function AuthApiKey(regime: string, credentials: ApiKeyCredential
|
|
|
310
314
|
* `RuntimeSetupOptions`). Undeclared means DEPLOYED, so a forgotten wiring call refuses the endpoint
|
|
311
315
|
* rather than exposing it.
|
|
312
316
|
*/
|
|
313
|
-
export declare function
|
|
317
|
+
export declare function WpAuthLocalOnly(): MethodDecorator;
|
|
314
318
|
/**
|
|
315
319
|
* Get the base path from @ApiPath decorator.
|
|
316
320
|
*/
|
|
@@ -352,20 +356,20 @@ export declare function assertEveryExternalEndpointDeclaresCaller(apiClass: Func
|
|
|
352
356
|
export declare function isFormPost(apiClass: Function, methodName: string): boolean;
|
|
353
357
|
/**
|
|
354
358
|
* True when the method's @Endpoint declared `{ rawBody: true }` — the transport must retain the
|
|
355
|
-
* verbatim bytes + absolute url for an {@link
|
|
359
|
+
* verbatim bytes + absolute url for an {@link WpAuthWebhook} hook to verify.
|
|
356
360
|
*/
|
|
357
361
|
export declare function isRawBody(apiClass: Function, methodName: string): boolean;
|
|
358
362
|
/**
|
|
359
|
-
* Fail-fast at wiring time when an `@
|
|
363
|
+
* Fail-fast at wiring time when an `@WpAuthWebhook` endpoint did not ask the transport to keep the
|
|
360
364
|
* bytes it is supposed to verify. A hook with nothing to verify is a MISCONFIGURATION, and it must
|
|
361
365
|
* surface at startup, naming the fix — not as a 401 in production on exactly the traffic the endpoint
|
|
362
366
|
* exists for.
|
|
363
367
|
*
|
|
364
368
|
* This pairing is a runtime assert rather than a type because the two halves live on DIFFERENT
|
|
365
|
-
* decorators (`@
|
|
369
|
+
* decorators (`@WpAuthWebhook` and `@Endpoint`), and no union over one decorator's argument can say
|
|
366
370
|
* anything about the other's.
|
|
367
371
|
*
|
|
368
|
-
* @throws Error naming the first `@
|
|
372
|
+
* @throws Error naming the first `@WpAuthWebhook` endpoint missing `{ rawBody: true }`.
|
|
369
373
|
*/
|
|
370
374
|
export declare function assertEveryWebhookEndpointRetainsRawBody(apiClass: Function): void;
|
|
371
375
|
/**
|
|
@@ -373,15 +377,14 @@ export declare function assertEveryWebhookEndpointRetainsRawBody(apiClass: Funct
|
|
|
373
377
|
*/
|
|
374
378
|
export declare function isApiPath(apiClass: Function): boolean;
|
|
375
379
|
/**
|
|
376
|
-
* Get auth metadata
|
|
377
|
-
* Method-level auth takes precedence over class-level auth.
|
|
380
|
+
* Get method-level auth metadata. Class-level authorization is forbidden.
|
|
378
381
|
*/
|
|
379
|
-
export declare function getAuthMeta(apiClass: Function, methodName
|
|
382
|
+
export declare function getAuthMeta(apiClass: Function, methodName: string): AuthMeta | undefined;
|
|
380
383
|
/**
|
|
381
|
-
* Get the auth mode for a method
|
|
384
|
+
* Get the auth mode for a method, or undefined.
|
|
382
385
|
* Convenience wrapper over getAuthMeta for callers that only want the mode.
|
|
383
386
|
*/
|
|
384
|
-
export declare function getAuthMode(apiClass: Function, methodName
|
|
387
|
+
export declare function getAuthMode(apiClass: Function, methodName: string): AuthMode | undefined;
|
|
385
388
|
/**
|
|
386
389
|
* The ONE prescription for "this endpoint declares no auth", shared by the two places that raise it
|
|
387
390
|
* (here and http-routing's ApiRoutingFactory) because they had drifted into teaching different menus.
|