@webpieces/core-util 0.4.923 → 0.4.925

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.
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WpAuthOidcCompileAssertions = void 0;
4
+ const auth_mode_1 = require("./auth-mode");
5
+ const decorators_1 = require("./decorators");
6
+ /**
7
+ * COMPILE-TIME assertions for the two OIDC descriptors and the `oidc` member of the {@link AuthMode}
8
+ * union. Each `@ts-expect-error` below FAILS THE BUILD (TS2578, "unused '@ts-expect-error' directive")
9
+ * if the line it guards ever starts compiling.
10
+ *
11
+ * WHY THIS IS NOT A `.spec.ts` FILE — same reason as `WpAuthApiKeyCompileAssertions.ts`:
12
+ * tsconfig.lib.json EXCLUDES specs and vitest strips types with esbuild, so a `@ts-expect-error` in a
13
+ * spec is inert and the suite passes whether or not the guarded line really errors.
14
+ *
15
+ * WHAT IT PINS.
16
+ *
17
+ * 1. `oidcSvcs([...])` names AT LEAST ONE service account. The removed `oidc()` meant "any
18
+ * Google-signed caller" when it named nobody, so an empty list is a compile error here rather than
19
+ * a policy somebody could mistake for that grant (shim shape #4). `AuthDeclaration` keeps a runtime
20
+ * backstop only for a list that arrives around the type.
21
+ * 2. The two scopes are MUTUALLY exclusive shapes: a same-project descriptor carries no `callers`, and
22
+ * a services descriptor cannot drop them.
23
+ * 3. The removed shape, `{ kind: 'oidc', callers }` with no `callerScope`, no longer type-checks, so a
24
+ * hand-written mode cannot reintroduce the trust-the-edge grant through the union.
25
+ * 4. One endpoint MAY pair one descriptor of each scope with other credentials. Two of one scope is a
26
+ * runtime refusal in `AuthDeclaration`: a tuple of union members cannot express "at most one each".
27
+ */
28
+ class WpAuthOidcCompileAssertions {
29
+ /** The legitimate spellings must keep compiling; asserted by the ABSENCE of an error. */
30
+ legitimate() {
31
+ void (0, decorators_1.WpAuth)([(0, auth_mode_1.oidcSameProject)()]);
32
+ void (0, decorators_1.WpAuth)([(0, auth_mode_1.oidcSvcs)(['self'])]);
33
+ void (0, decorators_1.WpAuth)([(0, auth_mode_1.oidcSvcs)(['svc-a', 'partner-sa@other-project.iam.gserviceaccount.com'])]);
34
+ void (0, decorators_1.WpAuth)([
35
+ (0, auth_mode_1.oidcSameProject)(),
36
+ (0, auth_mode_1.oidcSvcs)(['partner-sa@other-project.iam.gserviceaccount.com']),
37
+ (0, auth_mode_1.jwt)(),
38
+ ]);
39
+ }
40
+ rejected() {
41
+ // @ts-expect-error an empty list names nobody; oidcSameProject() accepts this project's service accounts
42
+ void (0, auth_mode_1.oidcSvcs)([]);
43
+ // @ts-expect-error the service accounts are ONE list, not rest arguments
44
+ void (0, auth_mode_1.oidcSvcs)('svc-a', 'svc-b');
45
+ // @ts-expect-error a same-project descriptor takes no caller list
46
+ void (0, auth_mode_1.oidcSameProject)(['svc-a']);
47
+ // @ts-expect-error a same-project descriptor carries no callers
48
+ const extra = { kind: 'oidc', callerScope: 'same-project', callers: ['a'] };
49
+ void extra;
50
+ // @ts-expect-error a services descriptor must carry its callers
51
+ const missing = { kind: 'oidc', callerScope: 'services' };
52
+ void missing;
53
+ // @ts-expect-error the removed trust-the-edge shape (callers, no callerScope) is not an AuthMode
54
+ const removedShape = { kind: 'oidc', callers: [] };
55
+ void removedShape;
56
+ }
57
+ }
58
+ exports.WpAuthOidcCompileAssertions = WpAuthOidcCompileAssertions;
59
+ //# sourceMappingURL=WpAuthOidcCompileAssertions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WpAuthOidcCompileAssertions.js","sourceRoot":"","sources":["../../../../../../packages/core/core-util/src/http/WpAuthOidcCompileAssertions.ts"],"names":[],"mappings":";;;AAAA,2CAAuF;AACvF,6CAAsC;AAEtC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAa,2BAA2B;IACpC,yFAAyF;IACzF,UAAU;QACN,KAAK,IAAA,mBAAM,EAAC,CAAC,IAAA,2BAAe,GAAE,CAAC,CAAC,CAAC;QACjC,KAAK,IAAA,mBAAM,EAAC,CAAC,IAAA,oBAAQ,EAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAClC,KAAK,IAAA,mBAAM,EAAC,CAAC,IAAA,oBAAQ,EAAC,CAAC,OAAO,EAAE,kDAAkD,CAAC,CAAC,CAAC,CAAC,CAAC;QACvF,KAAK,IAAA,mBAAM,EAAC;YACR,IAAA,2BAAe,GAAE;YACjB,IAAA,oBAAQ,EAAC,CAAC,kDAAkD,CAAC,CAAC;YAC9D,IAAA,eAAG,GAAE;SACR,CAAC,CAAC;IACP,CAAC;IAED,QAAQ;QACJ,yGAAyG;QACzG,KAAK,IAAA,oBAAQ,EAAC,EAAE,CAAC,CAAC;QAClB,yEAAyE;QACzE,KAAK,IAAA,oBAAQ,EAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAChC,kEAAkE;QAClE,KAAK,IAAA,2BAAe,EAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QAChC,gEAAgE;QAChE,MAAM,KAAK,GAAmB,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5F,KAAK,KAAK,CAAC;QACX,gEAAgE;QAChE,MAAM,OAAO,GAAmB,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC;QAC1E,KAAK,OAAO,CAAC;QACb,iGAAiG;QACjG,MAAM,YAAY,GAAa,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QAC7D,KAAK,YAAY,CAAC;IACtB,CAAC;CACJ;AA9BD,kEA8BC","sourcesContent":["import { AuthMode, jwt, OidcAuthMethod, oidcSameProject, oidcSvcs } from './auth-mode';\nimport { WpAuth } from './decorators';\n\n/**\n * COMPILE-TIME assertions for the two OIDC descriptors and the `oidc` member of the {@link AuthMode}\n * union. Each `@ts-expect-error` below FAILS THE BUILD (TS2578, \"unused '@ts-expect-error' directive\")\n * if the line it guards ever starts compiling.\n *\n * WHY THIS IS NOT A `.spec.ts` FILE — same reason as `WpAuthApiKeyCompileAssertions.ts`:\n * tsconfig.lib.json EXCLUDES specs and vitest strips types with esbuild, so a `@ts-expect-error` in a\n * spec is inert and the suite passes whether or not the guarded line really errors.\n *\n * WHAT IT PINS.\n *\n * 1. `oidcSvcs([...])` names AT LEAST ONE service account. The removed `oidc()` meant \"any\n * Google-signed caller\" when it named nobody, so an empty list is a compile error here rather than\n * a policy somebody could mistake for that grant (shim shape #4). `AuthDeclaration` keeps a runtime\n * backstop only for a list that arrives around the type.\n * 2. The two scopes are MUTUALLY exclusive shapes: a same-project descriptor carries no `callers`, and\n * a services descriptor cannot drop them.\n * 3. The removed shape, `{ kind: 'oidc', callers }` with no `callerScope`, no longer type-checks, so a\n * hand-written mode cannot reintroduce the trust-the-edge grant through the union.\n * 4. One endpoint MAY pair one descriptor of each scope with other credentials. Two of one scope is a\n * runtime refusal in `AuthDeclaration`: a tuple of union members cannot express \"at most one each\".\n */\nexport class WpAuthOidcCompileAssertions {\n /** The legitimate spellings must keep compiling; asserted by the ABSENCE of an error. */\n legitimate(): void {\n void WpAuth([oidcSameProject()]);\n void WpAuth([oidcSvcs(['self'])]);\n void WpAuth([oidcSvcs(['svc-a', 'partner-sa@other-project.iam.gserviceaccount.com'])]);\n void WpAuth([\n oidcSameProject(),\n oidcSvcs(['partner-sa@other-project.iam.gserviceaccount.com']),\n jwt(),\n ]);\n }\n\n rejected(): void {\n // @ts-expect-error an empty list names nobody; oidcSameProject() accepts this project's service accounts\n void oidcSvcs([]);\n // @ts-expect-error the service accounts are ONE list, not rest arguments\n void oidcSvcs('svc-a', 'svc-b');\n // @ts-expect-error a same-project descriptor takes no caller list\n void oidcSameProject(['svc-a']);\n // @ts-expect-error a same-project descriptor carries no callers\n const extra: OidcAuthMethod = { kind: 'oidc', callerScope: 'same-project', callers: ['a'] };\n void extra;\n // @ts-expect-error a services descriptor must carry its callers\n const missing: OidcAuthMethod = { kind: 'oidc', callerScope: 'services' };\n void missing;\n // @ts-expect-error the removed trust-the-edge shape (callers, no callerScope) is not an AuthMode\n const removedShape: AuthMode = { kind: 'oidc', callers: [] };\n void removedShape;\n }\n}\n"]}
@@ -20,13 +20,38 @@ export type ApiKeyCredential = {
20
20
  description?: string;
21
21
  };
22
22
  export type ApiKeyCredentials = readonly [ApiKeyCredential, ...ApiKeyCredential[]];
23
+ /**
24
+ * The service accounts an `oidcSvcs([...])` endpoint names, at least one: an empty list is not a
25
+ * policy anybody could mean, so it does not compile. Each entry resolves as `'self'` (this service's
26
+ * runtime SA), a bare id (`<id>@<project>.iam.gserviceaccount.com`) or a full email (verbatim).
27
+ */
28
+ export type OidcCallers = readonly [string, ...string[]];
29
+ /**
30
+ * WHICH Google-signed callers an OIDC endpoint accepts, named by `callerScope`:
31
+ * - `'same-project'` (`oidcSameProject()`): any service account of THIS GCP project. Off GCP there is
32
+ * no project, so the check is open.
33
+ * - `'services'` (`oidcSvcs([...])`): exactly the listed service accounts, which may belong to other
34
+ * projects.
35
+ * One endpoint may declare one of each; see {@link OidcAuthMethods}.
36
+ */
37
+ export type OidcAuthMethod = {
38
+ kind: 'oidc';
39
+ callerScope: 'same-project';
40
+ } | {
41
+ kind: 'oidc';
42
+ callerScope: 'services';
43
+ callers: OidcCallers;
44
+ };
45
+ /**
46
+ * The OIDC methods ONE endpoint declares, in declaration order: one, or one per caller scope. They are
47
+ * ONE bearer credential, so a verifier receives them together, checks the token's signature once, and
48
+ * admits the call when ANY of them admits the caller.
49
+ */
50
+ export type OidcAuthMethods = readonly [OidcAuthMethod, ...OidcAuthMethod[]];
23
51
  /** One concrete mechanism; user policy belongs exclusively to WpAuthorization. */
24
52
  export type AuthMethod = {
25
53
  kind: 'jwt';
26
- } | {
27
- kind: 'oidc';
28
- callers: readonly string[];
29
- } | {
54
+ } | OidcAuthMethod | {
30
55
  kind: 'shared-secret';
31
56
  secretKey: string;
32
57
  } | {
@@ -50,7 +75,20 @@ export declare class AuthMeta {
50
75
  }
51
76
  export declare class AuthDeclaration {
52
77
  static validate(meta: AuthMeta): void;
78
+ /**
79
+ * One method per credential kind, except OIDC: one per `callerScope`, so `oidcSameProject()` and
80
+ * `oidcSvcs([...])` may pair on one endpoint (this project's accounts OR the listed ones). They are
81
+ * still ONE bearer credential, which AuthFilter verifies once for both.
82
+ */
83
+ private static uniquenessKey;
53
84
  private static validateMethod;
85
+ /**
86
+ * The keys an OIDC descriptor may carry, after checking its scope. `OidcCallers` already makes an
87
+ * empty `oidcSvcs([])` a compile error; this is the backstop for a list that reached the decorator
88
+ * around the type (a cast, a spread of a runtime array, plain JS), so it fails when the decorator
89
+ * is evaluated instead of reaching a verifier.
90
+ */
91
+ private static oidcKeys;
54
92
  /**
55
93
  * A header credential's key must be a ContextKey that rides the wire. `httpHeader` is optional on
56
94
  * ContextKey itself (most keys never leave the process), and the factories' explicit value-type
@@ -62,7 +100,8 @@ export declare class AuthDeclaration {
62
100
  private static requireText;
63
101
  }
64
102
  export declare function jwt(): AuthMethod;
65
- export declare function oidc(...callers: string[]): AuthMethod;
103
+ export declare function oidcSameProject(): OidcAuthMethod;
104
+ export declare function oidcSvcs(callers: OidcCallers): OidcAuthMethod;
66
105
  export declare function sharedSecret(secretKey: string): AuthMethod;
67
106
  export declare function webhook(name: string): AuthMethod;
68
107
  export declare function apiKey(regime: string, credentials: ApiKeyCredentials): AuthMethod;
@@ -2,7 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AuthDeclaration = exports.AuthMeta = void 0;
4
4
  exports.jwt = jwt;
5
- exports.oidc = oidc;
5
+ exports.oidcSameProject = oidcSameProject;
6
+ exports.oidcSvcs = oidcSvcs;
6
7
  exports.sharedSecret = sharedSecret;
7
8
  exports.webhook = webhook;
8
9
  exports.apiKey = apiKey;
@@ -20,7 +21,9 @@ class AuthMeta {
20
21
  // webpieces-disable no-function-outside-class -- stateless contract validation or scope metadata reader used before DI registration
21
22
  static snapshot(method) {
22
23
  switch (method.kind) {
23
- case 'oidc': return Object.freeze({ ...method, callers: Object.freeze([...method.callers]) });
24
+ case 'oidc': return method.callerScope === 'services'
25
+ ? Object.freeze({ ...method, callers: Object.freeze([...method.callers]) })
26
+ : Object.freeze({ ...method });
24
27
  case 'apikey': return Object.freeze({ ...method, credentials: Object.freeze(method.credentials.map((credential) => Object.freeze({ ...credential }))) });
25
28
  default: return Object.freeze({ ...method });
26
29
  }
@@ -34,9 +37,9 @@ class AuthDeclaration {
34
37
  throw new Error('@WpAuth requires a nonempty methods tuple.');
35
38
  const kinds = new Set();
36
39
  for (const method of meta.methods) {
37
- if (!method || typeof method !== 'object' || kinds.has(method.kind))
40
+ if (!method || typeof method !== 'object' || kinds.has(this.uniquenessKey(method)))
38
41
  throw new Error('@WpAuth rejects duplicate or invalid credential methods.');
39
- kinds.add(method.kind);
42
+ kinds.add(this.uniquenessKey(method));
40
43
  this.validateMethod(method);
41
44
  }
42
45
  if (kinds.has('public')) {
@@ -47,6 +50,15 @@ class AuthDeclaration {
47
50
  else if (meta.publicReason !== undefined)
48
51
  throw new Error('Protected @WpAuth rejects public reasons.');
49
52
  }
53
+ /**
54
+ * One method per credential kind, except OIDC: one per `callerScope`, so `oidcSameProject()` and
55
+ * `oidcSvcs([...])` may pair on one endpoint (this project's accounts OR the listed ones). They are
56
+ * still ONE bearer credential, which AuthFilter verifies once for both.
57
+ */
58
+ // webpieces-disable no-function-outside-class -- stateless contract validation or scope metadata reader used before DI registration
59
+ static uniquenessKey(method) {
60
+ return method.kind === 'oidc' ? `oidc:${method.callerScope}` : method.kind;
61
+ }
50
62
  // webpieces-disable no-function-outside-class -- stateless contract validation or scope metadata reader used before DI registration
51
63
  static validateMethod(method) {
52
64
  let keys;
@@ -56,9 +68,7 @@ class AuthDeclaration {
56
68
  keys = ['kind'];
57
69
  break;
58
70
  case 'oidc':
59
- keys = ['kind', 'callers'];
60
- if (!Array.isArray(method.callers) || !method.callers.every((caller) => typeof caller === 'string' && caller.trim().length > 0))
61
- throw new Error('oidc(...) requires valid caller names.');
71
+ keys = this.oidcKeys(method);
62
72
  break;
63
73
  case 'shared-secret':
64
74
  keys = ['kind', 'secretKey'];
@@ -80,13 +90,30 @@ class AuthDeclaration {
80
90
  throw new Error('Invalid API-key credential location.');
81
91
  }
82
92
  break;
83
- default: throw new Error('Unknown @WpAuth method; use jwt/oidc/sharedSecret/webhook/apiKey descriptors.');
93
+ default: throw new Error('Unknown @WpAuth method; use jwt/oidcSameProject/oidcSvcs/sharedSecret/webhook/apiKey descriptors.');
84
94
  }
85
95
  for (const key of Object.keys(method)) {
86
96
  if (!keys.includes(key))
87
97
  throw new Error(`Auth method rejects '${key}'; operation policy belongs in @WpAuthorization.`);
88
98
  }
89
99
  }
100
+ /**
101
+ * The keys an OIDC descriptor may carry, after checking its scope. `OidcCallers` already makes an
102
+ * empty `oidcSvcs([])` a compile error; this is the backstop for a list that reached the decorator
103
+ * around the type (a cast, a spread of a runtime array, plain JS), so it fails when the decorator
104
+ * is evaluated instead of reaching a verifier.
105
+ */
106
+ // webpieces-disable no-function-outside-class -- stateless contract validation or scope metadata reader used before DI registration
107
+ static oidcKeys(method) {
108
+ if (method.callerScope === 'same-project')
109
+ return ['kind', 'callerScope'];
110
+ if (method.callerScope !== 'services')
111
+ throw new Error("Unknown OIDC callerScope; use oidcSameProject() or oidcSvcs(['svc-a']).");
112
+ if (!Array.isArray(method.callers) || method.callers.length === 0 || !method.callers.every((caller) => typeof caller === 'string' && caller.trim().length > 0)) {
113
+ throw new Error("oidcSvcs([...]) requires at least one nonblank service account; use oidcSameProject() to accept this GCP project's service accounts.");
114
+ }
115
+ return ['kind', 'callerScope', 'callers'];
116
+ }
90
117
  /**
91
118
  * A header credential's key must be a ContextKey that rides the wire. `httpHeader` is optional on
92
119
  * ContextKey itself (most keys never leave the process), and the factories' explicit value-type
@@ -113,7 +140,9 @@ exports.AuthDeclaration = AuthDeclaration;
113
140
  // webpieces-disable no-function-outside-class -- canonical credential descriptor factory
114
141
  function jwt() { return { kind: 'jwt' }; }
115
142
  // webpieces-disable no-function-outside-class -- canonical credential descriptor factory
116
- function oidc(...callers) { return { kind: 'oidc', callers }; }
143
+ function oidcSameProject() { return { kind: 'oidc', callerScope: 'same-project' }; }
144
+ // webpieces-disable no-function-outside-class -- canonical credential descriptor factory
145
+ function oidcSvcs(callers) { return { kind: 'oidc', callerScope: 'services', callers }; }
117
146
  // webpieces-disable no-function-outside-class -- canonical credential descriptor factory
118
147
  function sharedSecret(secretKey) { return { kind: 'shared-secret', secretKey }; }
119
148
  // webpieces-disable no-function-outside-class -- canonical credential descriptor factory
@@ -1 +1 @@
1
- {"version":3,"file":"auth-mode.js","sourceRoot":"","sources":["../../../../../../packages/core/core-util/src/http/auth-mode.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AnyContextKey } from '../ContextKey';\n\n/**\n * WHERE one api-key credential rides.\n *\n * A header credential names the {@link AnyContextKey ContextKey} that carries it — NEVER a header-name\n * string. The key's `httpHeader` is the wire name, so the ONE definition of each header (the\n * ContextKey) is reused on every surface: `RequestContext` put/get, the client/server header\n * transfer, this declaration, and the published OpenAPI document. A string here was a second copy a\n * rename left stale (#1249). The key MUST declare an `httpHeader` — {@link AuthDeclaration} refuses\n * one that does not, and the OpenAPI generator reads the header name off the key's\n * `ContextKey.trusted(...)` / `ContextKey.untrusted(...)` definition.\n */\nexport type ApiKeyCredential =\n | { in: 'header'; key: AnyContextKey; description?: string }\n | { in: 'bearer'; key?: never; description?: string };\n\nexport type ApiKeyCredentials = readonly [ApiKeyCredential, ...ApiKeyCredential[]];\n\n/** One concrete mechanism; user policy belongs exclusively to WpAuthorization. */\nexport type AuthMethod =\n | { kind: 'jwt' }\n | { kind: 'oidc'; callers: readonly string[] }\n | { kind: 'shared-secret'; secretKey: string }\n | { kind: 'webhook'; name: string }\n | { kind: 'apikey'; regime: string; credentials: ApiKeyCredentials };\n\nexport type AuthMethods = readonly [AuthMethod, ...AuthMethod[]];\nexport type AuthMode = AuthMethod | { kind: 'public' };\n\n/** Alternatives remain unresolved until a concrete mechanism is chosen for this hop. */\nexport class AuthMeta {\n readonly methods: readonly [AuthMode, ...AuthMode[]];\n\n constructor(\n methods: readonly [AuthMode, ...AuthMode[]],\n public readonly publicReason: string | undefined,\n ) {\n this.methods = methods;\n AuthDeclaration.validate(this);\n this.methods = Object.freeze(methods.map((method: AuthMode) => AuthMeta.snapshot(method))) as readonly [AuthMode, ...AuthMode[]];\n Object.freeze(this);\n }\n\n // webpieces-disable no-function-outside-class -- stateless contract validation or scope metadata reader used before DI registration\n private static snapshot(method: AuthMode): AuthMode {\n switch (method.kind) {\n case 'oidc': return Object.freeze({ ...method, callers: Object.freeze([...method.callers]) });\n case 'apikey': return Object.freeze({ ...method, credentials: Object.freeze(method.credentials.map((credential: ApiKeyCredential) => Object.freeze({ ...credential }))) as ApiKeyCredentials });\n default: return Object.freeze({ ...method });\n }\n }\n}\n\nexport class AuthDeclaration {\n // webpieces-disable no-function-outside-class -- stateless contract validation or scope metadata reader used before DI registration\n static validate(meta: AuthMeta): void {\n if (!Array.isArray(meta.methods) || meta.methods.length === 0) throw new Error('@WpAuth requires a nonempty methods tuple.');\n const kinds = new Set<string>();\n for (const method of meta.methods) {\n if (!method || typeof method !== 'object' || kinds.has(method.kind)) throw new Error('@WpAuth rejects duplicate or invalid credential methods.');\n kinds.add(method.kind);\n this.validateMethod(method);\n }\n if (kinds.has('public')) {\n if (meta.methods.length !== 1 || typeof meta.publicReason !== 'string' || !meta.publicReason.trim()) {\n throw new Error('Public auth must be declared separately with @WpAuthPublic(reason).');\n }\n } else if (meta.publicReason !== undefined) throw new Error('Protected @WpAuth rejects public reasons.');\n }\n\n // webpieces-disable no-function-outside-class -- stateless contract validation or scope metadata reader used before DI registration\n private static validateMethod(method: AuthMode): void {\n let keys: readonly string[];\n switch (method.kind) {\n case 'jwt':\n case 'public': keys = ['kind']; break;\n case 'oidc':\n keys = ['kind', 'callers'];\n if (!Array.isArray(method.callers) || !method.callers.every((caller: string) => typeof caller === 'string' && caller.trim().length > 0)) throw new Error('oidc(...) requires valid caller names.');\n break;\n case 'shared-secret':\n keys = ['kind', 'secretKey'];\n this.requireText(method.secretKey, 'sharedSecret'); break;\n case 'webhook':\n keys = ['kind', 'name'];\n this.requireText(method.name, 'webhook'); break;\n case 'apikey':\n keys = ['kind', 'regime', 'credentials'];\n this.requireText(method.regime, 'apiKey');\n if (!Array.isArray(method.credentials) || !method.credentials.length) throw new Error('apiKey(...) requires a nonempty credentials tuple.');\n for (const credential of method.credentials) {\n if (credential.in === 'header') this.requireHeaderKey(credential.key);\n else if (credential.in !== 'bearer' || Object.hasOwn(credential, 'key')) throw new Error('Invalid API-key credential location.');\n }\n break;\n default: throw new Error('Unknown @WpAuth method; use jwt/oidc/sharedSecret/webhook/apiKey descriptors.');\n }\n for (const key of Object.keys(method)) {\n if (!keys.includes(key)) throw new Error(`Auth method rejects '${key}'; operation policy belongs in @WpAuthorization.`);\n }\n }\n\n /**\n * A header credential's key must be a ContextKey that rides the wire. `httpHeader` is optional on\n * ContextKey itself (most keys never leave the process), and the factories' explicit value-type\n * argument (`ContextKey.untrusted<string>(...)`) stops TypeScript inferring whether one was\n * passed, so the type cannot say \"a key WITH a header\". It is checked once, when the contract is\n * decorated, and the OpenAPI generator refuses the same key statically.\n */\n // webpieces-disable no-function-outside-class -- stateless contract validation or scope metadata reader used before DI registration\n private static requireHeaderKey(key: AnyContextKey | undefined): void {\n if (!key || typeof key !== 'object' || typeof key.name !== 'string') {\n throw new Error(\"apiKey header credential requires `key`: the ContextKey carrying it, e.g. { in: 'header', key: MyKeys.API_KEY }.\");\n }\n if (typeof key.httpHeader !== 'string' || !key.httpHeader.trim()) {\n throw new Error(`apiKey header credential key '${key.name}' declares no httpHeader; define it with ContextKey.trusted(name, provenance, '<header>') or ContextKey.untrusted(name, '<header>').`);\n }\n }\n\n // webpieces-disable no-function-outside-class -- stateless contract validation or scope metadata reader used before DI registration\n private static requireText(value: string, label: string): void {\n if (typeof value !== 'string' || !value.trim()) throw new Error(`${label} requires a nonempty name.`);\n }\n}\n\n// webpieces-disable no-function-outside-class -- canonical credential descriptor factory\nexport function jwt(): AuthMethod { return { kind: 'jwt' }; }\n// webpieces-disable no-function-outside-class -- canonical credential descriptor factory\nexport function oidc(...callers: string[]): AuthMethod { return { kind: 'oidc', callers }; }\n// webpieces-disable no-function-outside-class -- canonical credential descriptor factory\nexport function sharedSecret(secretKey: string): AuthMethod { return { kind: 'shared-secret', secretKey }; }\n// webpieces-disable no-function-outside-class -- canonical credential descriptor factory\nexport function webhook(name: string): AuthMethod { return { kind: 'webhook', name }; }\n// webpieces-disable no-function-outside-class -- canonical credential descriptor factory\nexport function apiKey(regime: string, credentials: ApiKeyCredentials): AuthMethod { return { kind: 'apikey', regime, credentials }; }\n"]}
1
+ {"version":3,"file":"auth-mode.js","sourceRoot":"","sources":["../../../../../../packages/core/core-util/src/http/auth-mode.ts"],"names":[],"mappings":";;;AAkLA,kBAA6D;AAE7D,0CAA2G;AAE3G,4BAA6H;AAE7H,oCAA4G;AAE5G,0BAAuF;AAEvF,wBAAsI;AApItI,wFAAwF;AACxF,MAAa,QAAQ;IAKG;IAJX,OAAO,CAAqC;IAErD,YACI,OAA2C,EAC3B,YAAgC;QAAhC,iBAAY,GAAZ,YAAY,CAAoB;QAEhD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAgB,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAuC,CAAC;QACjI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAED,oIAAoI;IAC5H,MAAM,CAAC,QAAQ,CAAC,MAAgB;QACpC,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;YAClB,KAAK,MAAM,CAAC,CAAC,OAAO,MAAM,CAAC,WAAW,KAAK,UAAU;gBACjD,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,CAAgB,EAAE,CAAC;gBAC1F,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;YACnC,KAAK,QAAQ,CAAC,CAAC,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,UAA4B,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,UAAU,EAAE,CAAC,CAAC,CAAsB,EAAE,CAAC,CAAC;YAChM,OAAO,CAAC,CAAC,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;QACjD,CAAC;IACL,CAAC;CACJ;AAvBD,4BAuBC;AAED,MAAa,eAAe;IACxB,oIAAoI;IACpI,MAAM,CAAC,QAAQ,CAAC,IAAc;QAC1B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAC7H,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;QAChC,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAChC,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;YAChK,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;YACtC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAChC,CAAC;QACD,IAAI,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YACtB,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,IAAI,CAAC,YAAY,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,CAAC;gBAClG,MAAM,IAAI,KAAK,CAAC,qEAAqE,CAAC,CAAC;YAC3F,CAAC;QACL,CAAC;aAAM,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC7G,CAAC;IAED;;;;OAIG;IACH,oIAAoI;IAC5H,MAAM,CAAC,aAAa,CAAC,MAAgB;QACzC,OAAO,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,QAAQ,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC;IAC/E,CAAC;IAED,oIAAoI;IAC5H,MAAM,CAAC,cAAc,CAAC,MAAgB;QAC1C,IAAI,IAAuB,CAAC;QAC5B,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;YAClB,KAAK,KAAK,CAAC;YACX,KAAK,QAAQ;gBAAE,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;gBAAC,MAAM;YACtC,KAAK,MAAM;gBAAE,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;gBAAC,MAAM;YACjD,KAAK,eAAe;gBAChB,IAAI,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;gBAC7B,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;gBAAC,MAAM;YAC9D,KAAK,SAAS;gBACV,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;gBACxB,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;gBAAC,MAAM;YACpD,KAAK,QAAQ;gBACT,IAAI,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;gBACzC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;gBAC1C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM;oBAAE,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;gBAC5I,KAAK,MAAM,UAAU,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;oBAC1C,IAAI,UAAU,CAAC,EAAE,KAAK,QAAQ;wBAAE,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;yBACjE,IAAI,UAAU,CAAC,EAAE,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC;wBAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;gBACrI,CAAC;gBACD,MAAM;YACV,OAAO,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,mGAAmG,CAAC,CAAC;QAClI,CAAC;QACD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACpC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,GAAG,kDAAkD,CAAC,CAAC;QAC5H,CAAC;IACL,CAAC;IAED;;;;;OAKG;IACH,oIAAoI;IAC5H,MAAM,CAAC,QAAQ,CAAC,MAAsB;QAC1C,IAAI,MAAM,CAAC,WAAW,KAAK,cAAc;YAAE,OAAO,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;QAC1E,IAAI,MAAM,CAAC,WAAW,KAAK,UAAU;YAAE,MAAM,IAAI,KAAK,CAAC,yEAAyE,CAAC,CAAC;QAClI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,MAAc,EAAE,EAAE,CAAC,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;YACrK,MAAM,IAAI,KAAK,CAAC,sIAAsI,CAAC,CAAC;QAC5J,CAAC;QACD,OAAO,CAAC,MAAM,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC;IAC9C,CAAC;IAED;;;;;;OAMG;IACH,oIAAoI;IAC5H,MAAM,CAAC,gBAAgB,CAAC,GAA8B;QAC1D,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAClE,MAAM,IAAI,KAAK,CAAC,kHAAkH,CAAC,CAAC;QACxI,CAAC;QACD,IAAI,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC;YAC/D,MAAM,IAAI,KAAK,CAAC,iCAAiC,GAAG,CAAC,IAAI,sIAAsI,CAAC,CAAC;QACrM,CAAC;IACL,CAAC;IAED,oIAAoI;IAC5H,MAAM,CAAC,WAAW,CAAC,KAAa,EAAE,KAAa;QACnD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,4BAA4B,CAAC,CAAC;IAC1G,CAAC;CACJ;AA7FD,0CA6FC;AAED,yFAAyF;AACzF,SAAgB,GAAG,KAAiB,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;AAC7D,yFAAyF;AACzF,SAAgB,eAAe,KAAqB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC;AAC3G,yFAAyF;AACzF,SAAgB,QAAQ,CAAC,OAAoB,IAAoB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;AAC7H,yFAAyF;AACzF,SAAgB,YAAY,CAAC,SAAiB,IAAgB,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;AAC5G,yFAAyF;AACzF,SAAgB,OAAO,CAAC,IAAY,IAAgB,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACvF,yFAAyF;AACzF,SAAgB,MAAM,CAAC,MAAc,EAAE,WAA8B,IAAgB,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC","sourcesContent":["import type { AnyContextKey } from '../ContextKey';\n\n/**\n * WHERE one api-key credential rides.\n *\n * A header credential names the {@link AnyContextKey ContextKey} that carries it — NEVER a header-name\n * string. The key's `httpHeader` is the wire name, so the ONE definition of each header (the\n * ContextKey) is reused on every surface: `RequestContext` put/get, the client/server header\n * transfer, this declaration, and the published OpenAPI document. A string here was a second copy a\n * rename left stale (#1249). The key MUST declare an `httpHeader` — {@link AuthDeclaration} refuses\n * one that does not, and the OpenAPI generator reads the header name off the key's\n * `ContextKey.trusted(...)` / `ContextKey.untrusted(...)` definition.\n */\nexport type ApiKeyCredential =\n | { in: 'header'; key: AnyContextKey; description?: string }\n | { in: 'bearer'; key?: never; description?: string };\n\nexport type ApiKeyCredentials = readonly [ApiKeyCredential, ...ApiKeyCredential[]];\n\n/**\n * The service accounts an `oidcSvcs([...])` endpoint names, at least one: an empty list is not a\n * policy anybody could mean, so it does not compile. Each entry resolves as `'self'` (this service's\n * runtime SA), a bare id (`<id>@<project>.iam.gserviceaccount.com`) or a full email (verbatim).\n */\nexport type OidcCallers = readonly [string, ...string[]];\n\n/**\n * WHICH Google-signed callers an OIDC endpoint accepts, named by `callerScope`:\n * - `'same-project'` (`oidcSameProject()`): any service account of THIS GCP project. Off GCP there is\n * no project, so the check is open.\n * - `'services'` (`oidcSvcs([...])`): exactly the listed service accounts, which may belong to other\n * projects.\n * One endpoint may declare one of each; see {@link OidcAuthMethods}.\n */\nexport type OidcAuthMethod =\n | { kind: 'oidc'; callerScope: 'same-project' }\n | { kind: 'oidc'; callerScope: 'services'; callers: OidcCallers };\n\n/**\n * The OIDC methods ONE endpoint declares, in declaration order: one, or one per caller scope. They are\n * ONE bearer credential, so a verifier receives them together, checks the token's signature once, and\n * admits the call when ANY of them admits the caller.\n */\nexport type OidcAuthMethods = readonly [OidcAuthMethod, ...OidcAuthMethod[]];\n\n/** One concrete mechanism; user policy belongs exclusively to WpAuthorization. */\nexport type AuthMethod =\n | { kind: 'jwt' }\n | OidcAuthMethod\n | { kind: 'shared-secret'; secretKey: string }\n | { kind: 'webhook'; name: string }\n | { kind: 'apikey'; regime: string; credentials: ApiKeyCredentials };\n\nexport type AuthMethods = readonly [AuthMethod, ...AuthMethod[]];\nexport type AuthMode = AuthMethod | { kind: 'public' };\n\n/** Alternatives remain unresolved until a concrete mechanism is chosen for this hop. */\nexport class AuthMeta {\n readonly methods: readonly [AuthMode, ...AuthMode[]];\n\n constructor(\n methods: readonly [AuthMode, ...AuthMode[]],\n public readonly publicReason: string | undefined,\n ) {\n this.methods = methods;\n AuthDeclaration.validate(this);\n this.methods = Object.freeze(methods.map((method: AuthMode) => AuthMeta.snapshot(method))) as readonly [AuthMode, ...AuthMode[]];\n Object.freeze(this);\n }\n\n // webpieces-disable no-function-outside-class -- stateless contract validation or scope metadata reader used before DI registration\n private static snapshot(method: AuthMode): AuthMode {\n switch (method.kind) {\n case 'oidc': return method.callerScope === 'services'\n ? Object.freeze({ ...method, callers: Object.freeze([...method.callers]) as OidcCallers })\n : Object.freeze({ ...method });\n case 'apikey': return Object.freeze({ ...method, credentials: Object.freeze(method.credentials.map((credential: ApiKeyCredential) => Object.freeze({ ...credential }))) as ApiKeyCredentials });\n default: return Object.freeze({ ...method });\n }\n }\n}\n\nexport class AuthDeclaration {\n // webpieces-disable no-function-outside-class -- stateless contract validation or scope metadata reader used before DI registration\n static validate(meta: AuthMeta): void {\n if (!Array.isArray(meta.methods) || meta.methods.length === 0) throw new Error('@WpAuth requires a nonempty methods tuple.');\n const kinds = new Set<string>();\n for (const method of meta.methods) {\n if (!method || typeof method !== 'object' || kinds.has(this.uniquenessKey(method))) throw new Error('@WpAuth rejects duplicate or invalid credential methods.');\n kinds.add(this.uniquenessKey(method));\n this.validateMethod(method);\n }\n if (kinds.has('public')) {\n if (meta.methods.length !== 1 || typeof meta.publicReason !== 'string' || !meta.publicReason.trim()) {\n throw new Error('Public auth must be declared separately with @WpAuthPublic(reason).');\n }\n } else if (meta.publicReason !== undefined) throw new Error('Protected @WpAuth rejects public reasons.');\n }\n\n /**\n * One method per credential kind, except OIDC: one per `callerScope`, so `oidcSameProject()` and\n * `oidcSvcs([...])` may pair on one endpoint (this project's accounts OR the listed ones). They are\n * still ONE bearer credential, which AuthFilter verifies once for both.\n */\n // webpieces-disable no-function-outside-class -- stateless contract validation or scope metadata reader used before DI registration\n private static uniquenessKey(method: AuthMode): string {\n return method.kind === 'oidc' ? `oidc:${method.callerScope}` : method.kind;\n }\n\n // webpieces-disable no-function-outside-class -- stateless contract validation or scope metadata reader used before DI registration\n private static validateMethod(method: AuthMode): void {\n let keys: readonly string[];\n switch (method.kind) {\n case 'jwt':\n case 'public': keys = ['kind']; break;\n case 'oidc': keys = this.oidcKeys(method); break;\n case 'shared-secret':\n keys = ['kind', 'secretKey'];\n this.requireText(method.secretKey, 'sharedSecret'); break;\n case 'webhook':\n keys = ['kind', 'name'];\n this.requireText(method.name, 'webhook'); break;\n case 'apikey':\n keys = ['kind', 'regime', 'credentials'];\n this.requireText(method.regime, 'apiKey');\n if (!Array.isArray(method.credentials) || !method.credentials.length) throw new Error('apiKey(...) requires a nonempty credentials tuple.');\n for (const credential of method.credentials) {\n if (credential.in === 'header') this.requireHeaderKey(credential.key);\n else if (credential.in !== 'bearer' || Object.hasOwn(credential, 'key')) throw new Error('Invalid API-key credential location.');\n }\n break;\n default: throw new Error('Unknown @WpAuth method; use jwt/oidcSameProject/oidcSvcs/sharedSecret/webhook/apiKey descriptors.');\n }\n for (const key of Object.keys(method)) {\n if (!keys.includes(key)) throw new Error(`Auth method rejects '${key}'; operation policy belongs in @WpAuthorization.`);\n }\n }\n\n /**\n * The keys an OIDC descriptor may carry, after checking its scope. `OidcCallers` already makes an\n * empty `oidcSvcs([])` a compile error; this is the backstop for a list that reached the decorator\n * around the type (a cast, a spread of a runtime array, plain JS), so it fails when the decorator\n * is evaluated instead of reaching a verifier.\n */\n // webpieces-disable no-function-outside-class -- stateless contract validation or scope metadata reader used before DI registration\n private static oidcKeys(method: OidcAuthMethod): readonly string[] {\n if (method.callerScope === 'same-project') return ['kind', 'callerScope'];\n if (method.callerScope !== 'services') throw new Error(\"Unknown OIDC callerScope; use oidcSameProject() or oidcSvcs(['svc-a']).\");\n if (!Array.isArray(method.callers) || method.callers.length === 0 || !method.callers.every((caller: string) => typeof caller === 'string' && caller.trim().length > 0)) {\n throw new Error(\"oidcSvcs([...]) requires at least one nonblank service account; use oidcSameProject() to accept this GCP project's service accounts.\");\n }\n return ['kind', 'callerScope', 'callers'];\n }\n\n /**\n * A header credential's key must be a ContextKey that rides the wire. `httpHeader` is optional on\n * ContextKey itself (most keys never leave the process), and the factories' explicit value-type\n * argument (`ContextKey.untrusted<string>(...)`) stops TypeScript inferring whether one was\n * passed, so the type cannot say \"a key WITH a header\". It is checked once, when the contract is\n * decorated, and the OpenAPI generator refuses the same key statically.\n */\n // webpieces-disable no-function-outside-class -- stateless contract validation or scope metadata reader used before DI registration\n private static requireHeaderKey(key: AnyContextKey | undefined): void {\n if (!key || typeof key !== 'object' || typeof key.name !== 'string') {\n throw new Error(\"apiKey header credential requires `key`: the ContextKey carrying it, e.g. { in: 'header', key: MyKeys.API_KEY }.\");\n }\n if (typeof key.httpHeader !== 'string' || !key.httpHeader.trim()) {\n throw new Error(`apiKey header credential key '${key.name}' declares no httpHeader; define it with ContextKey.trusted(name, provenance, '<header>') or ContextKey.untrusted(name, '<header>').`);\n }\n }\n\n // webpieces-disable no-function-outside-class -- stateless contract validation or scope metadata reader used before DI registration\n private static requireText(value: string, label: string): void {\n if (typeof value !== 'string' || !value.trim()) throw new Error(`${label} requires a nonempty name.`);\n }\n}\n\n// webpieces-disable no-function-outside-class -- canonical credential descriptor factory\nexport function jwt(): AuthMethod { return { kind: 'jwt' }; }\n// webpieces-disable no-function-outside-class -- canonical credential descriptor factory\nexport function oidcSameProject(): OidcAuthMethod { return { kind: 'oidc', callerScope: 'same-project' }; }\n// webpieces-disable no-function-outside-class -- canonical credential descriptor factory\nexport function oidcSvcs(callers: OidcCallers): OidcAuthMethod { return { kind: 'oidc', callerScope: 'services', callers }; }\n// webpieces-disable no-function-outside-class -- canonical credential descriptor factory\nexport function sharedSecret(secretKey: string): AuthMethod { return { kind: 'shared-secret', secretKey }; }\n// webpieces-disable no-function-outside-class -- canonical credential descriptor factory\nexport function webhook(name: string): AuthMethod { return { kind: 'webhook', name }; }\n// webpieces-disable no-function-outside-class -- canonical credential descriptor factory\nexport function apiKey(regime: string, credentials: ApiKeyCredentials): AuthMethod { return { kind: 'apikey', regime, credentials }; }\n"]}
@@ -392,7 +392,7 @@ function getAuthMeta(apiClass, methodName) {
392
392
  * the caller hits becomes the API they believe exists. It leads with the ROLE-GATED member on purpose —
393
393
  * the first thing offered should not be the widest grant.
394
394
  */
395
- exports.MISSING_AUTH_DECORATOR_FIX = "Declare @WpAuth([jwt(), oidc(...callers), sharedSecret(key), webhook(name), apiKey('regime', [{in: 'header', key: MyKeys.API_KEY}])]) " +
395
+ exports.MISSING_AUTH_DECORATOR_FIX = "Declare @WpAuth([jwt(), oidcSameProject() or oidcSvcs(['svc-a']), sharedSecret(key), webhook(name), apiKey('regime', [{in: 'header', key: MyKeys.API_KEY}])]) " +
396
396
  "or @WpAuthPublic('reason'), and exactly one @WpAuthorization on every endpoint. Add @WpLocalOnly() separately when locality is required.";
397
397
  /**
398
398
  * Fail-fast at wiring time if any endpoint lacks an auth mode. Both the server
@@ -1 +1 @@
1
- {"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../../../../../packages/core/core-util/src/http/decorators.ts"],"names":[],"mappings":"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","sourcesContent":["import 'reflect-metadata';\nimport { MaskSpec, MaskMode } from './LogFieldMask';\nimport {\n DEFAULT_CALLER_KIND,\n ENDPOINT_CALLER_KEY,\n ExternalCaller,\n getEndpointCaller,\n} from './external-caller';\n// The TYPE layer these decorators attach — split out for file size only (see auth-mode.ts).\nimport { AuthMeta, AuthMethods, AuthMode } from './auth-mode';\nimport {\n EndpointOperation,\n EndpointOptions,\n ExternalEndpointOptions,\n READ,\n WRITE_IDEMPOTENT,\n WRITE,\n} from './HttpEndpointOptions';\nimport { GET, HttpMethod, POST } from './HttpContract';\nimport { AuthorizationDeclaration, AuthorizationType, AUTHORIZATION_METHODS_KEY, getAuthorization } from './authorization';\nimport { HTTP_PARAMETERS_METADATA_KEY } from './http-parameter-decorators';\n\nexport type { EndpointOptions, ExternalEndpointOptions } from './HttpEndpointOptions';\nexport type { EndpointOperation } from './HttpEndpointOptions';\nexport { READ, WRITE_IDEMPOTENT, WRITE } from './HttpEndpointOptions';\nexport type { HttpMethod } from './HttpContract';\nexport { GET, POST } from './HttpContract';\nexport { PathParam, QueryParam, getHttpParameterDeclarations } from './http-parameter-decorators';\n\n/**\n * Metadata keys for storing API routing information.\n * These keys are used by both server-side (routing) and client-side (client generation).\n */\nexport const METADATA_KEYS = {\n API_PATH: 'webpieces:api-path',\n ENDPOINTS: 'webpieces:endpoints',\n AUTH_META: 'webpieces:auth-meta',\n /** Method names carrying one of the canonical authorization decorators. */\n AUTH_METHODS: 'webpieces:auth-methods',\n /** 'rpc' (default, sync request/response) vs 'pubsub' (fire-and-forget cloud task). */\n API_KIND: 'webpieces:api-kind',\n /** Per-method Cloud Tasks queue-name override (set via @Queue). */\n QUEUE_OVERRIDE: 'webpieces:queue-override',\n /** Per-method @Endpoint options (e.g. formPost), parallel to ENDPOINTS. */\n ENDPOINT_OPTIONS: 'webpieces:endpoint-options',\n /** Per-method required HTTP method, parallel to ENDPOINTS. */\n ENDPOINT_HTTP_METHOD: 'webpieces:endpoint-http-method',\n /** Per-method required read/write semantics, parallel to ENDPOINTS. */\n ENDPOINT_OPERATION: 'webpieces:endpoint-operation',\n /** Per-method @Endpoint trigger kind (rpc | cloudtasks | cron | external), parallel to ENDPOINTS. */\n ENDPOINT_KIND: 'webpieces:endpoint-kind',\n /** Per-method declared external CALLER (only for kind 'external'), parallel to ENDPOINTS. */\n ENDPOINT_CALLER: ENDPOINT_CALLER_KEY,\n /** Per-method @MaskLog spec (which DTO fields the LogApiCall path masks). */\n MASK_LOG: 'webpieces:mask-log',\n /** Per-method opt-in metadata for publishing an RPC endpoint as an MCP tool. */\n MCP_TOOLS: 'webpieces:mcp-tools',\n /** Per-method PERMANENT exclusion from MCP, with the reason — see @InvalidEndpointForMcp. */\n MCP_INVALID: 'webpieces:mcp-invalid',\n /** Per-method request/response event metadata for a typed streaming endpoint. */\n STREAM_ENDPOINTS: 'webpieces:stream-endpoints',\n /** Per-method MCP-user authorization, intentionally separate from HTTP hop auth. */\n LOCAL_ONLY: 'webpieces:local-only',\n /** Per-method explicit path/query parameter declarations, keyed by parameter index. */\n HTTP_PARAMETERS: HTTP_PARAMETERS_METADATA_KEY,\n};\n\n/** Nominal backing keeps raw string literals out of endpoint declarations. */\nenum EndpointKindValue {\n RPC = 'rpc',\n CLOUDTASKS = 'cloudtasks',\n CRON = 'cron',\n EXTERNAL = 'external',\n}\n\n/** Short, statically importable decorator arguments. */\nexport const RPC = EndpointKindValue.RPC;\nexport const CLOUDTASKS = EndpointKindValue.CLOUDTASKS;\nexport const CRON = EndpointKindValue.CRON;\nexport const EXTERNAL = EndpointKindValue.EXTERNAL;\n\n/** Runtime trigger/delivery owner used by validation, architecture, and infrastructure tooling. */\nexport type EndpointKind = typeof RPC | typeof CLOUDTASKS | typeof CRON | typeof EXTERNAL;\n\n/** Class decorator that sets the shared base path for all endpoints. */\nexport function ApiPath(basePath: string): ClassDecorator {\n return (target: Function) => {\n if (Reflect.hasMetadata('webpieces:ipc-api-id', target)) {\n throw new Error(\n `Class ${target.name || 'Unknown'} cannot combine @ApiPath with @WpInternal.`,\n );\n }\n Reflect.defineMetadata(METADATA_KEYS.API_PATH, basePath, target);\n\n // Initialize endpoints map if not exists\n if (!Reflect.hasMetadata(METADATA_KEYS.ENDPOINTS, target)) {\n Reflect.defineMetadata(METADATA_KEYS.ENDPOINTS, {}, target);\n }\n };\n}\n\n/**\n * Registers `@Endpoint(POST, path, WRITE, RPC)`. Method, operation, and trigger are required enum\n * values. Operation is independent of the HTTP verb. EXTERNAL additionally requires `calledBy`.\n * Each classification rides a parallel metadata map while ENDPOINTS remains method-name -> path.\n */\n// webpieces-disable no-function-outside-class -- decorator factory; decorators are inherently module-scope\nexport function Endpoint(\n httpMethod: HttpMethod,\n path: string,\n operation: EndpointOperation,\n kind: typeof EXTERNAL,\n options: ExternalEndpointOptions,\n): MethodDecorator;\n// webpieces-disable no-function-outside-class -- decorator factory; decorators are inherently module-scope\nexport function Endpoint(\n httpMethod: HttpMethod,\n path: string,\n operation: EndpointOperation,\n kind: Exclude<EndpointKind, typeof EXTERNAL>,\n options?: EndpointOptions,\n): MethodDecorator;\n// webpieces-disable no-function-outside-class -- decorator factory; decorators are inherently module-scope\nexport function Endpoint(\n httpMethod: HttpMethod,\n path: string,\n operation: EndpointOperation,\n kind: EndpointKind,\n options: EndpointOptions = {},\n): MethodDecorator {\n validateEndpointClassification(httpMethod, operation, kind);\n // webpieces-disable no-any-unknown -- reflect-metadata decorator API requires any\n return (target: any, propertyKey: string | symbol, _descriptor: PropertyDescriptor) => {\n const metadataTarget = typeof target === 'function' ? target : target.constructor;\n recordEndpointMetadata(\n metadataTarget,\n propertyKey as string,\n httpMethod,\n path,\n operation,\n kind,\n options,\n );\n };\n}\n\n// webpieces-disable no-function-outside-class -- runtime validation backs up nominal TS enums\nfunction validateEndpointClassification(\n httpMethod: HttpMethod,\n operation: EndpointOperation,\n kind: EndpointKind,\n): void {\n if (!isHttpMethod(httpMethod)) {\n throw new Error(\n `@Endpoint httpMethod must be GET or POST, received '${String(httpMethod)}'.`,\n );\n }\n if (!isEndpointOperation(operation)) {\n throw new Error(\n `@Endpoint operation must be READ, WRITE_IDEMPOTENT, or WRITE, received '${String(operation)}'.`,\n );\n }\n if (!isEndpointKind(kind)) {\n throw new Error(\n `@Endpoint trigger must be RPC, CLOUDTASKS, CRON, or EXTERNAL, received '${String(kind)}'.`,\n );\n }\n}\n\n// webpieces-disable no-function-outside-class -- one metadata write shared by the decorator overloads\nfunction recordEndpointMetadata(\n metadataTarget: Function,\n propertyKey: string,\n httpMethod: HttpMethod,\n path: string,\n operation: EndpointOperation,\n kind: EndpointKind,\n options: EndpointOptions,\n): void {\n const endpoints: Record<string, string> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINTS, metadataTarget) || {};\n\n endpoints[propertyKey] = path;\n\n Reflect.defineMetadata(METADATA_KEYS.ENDPOINTS, endpoints, metadataTarget);\n\n const methods: Record<string, HttpMethod> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_HTTP_METHOD, metadataTarget) || {};\n methods[propertyKey] = httpMethod;\n Reflect.defineMetadata(METADATA_KEYS.ENDPOINT_HTTP_METHOD, methods, metadataTarget);\n\n const operations: Record<string, EndpointOperation> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_OPERATION, metadataTarget) || {};\n operations[propertyKey] = operation;\n Reflect.defineMetadata(METADATA_KEYS.ENDPOINT_OPERATION, operations, metadataTarget);\n\n const kinds: Record<string, EndpointKind> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_KIND, metadataTarget) || {};\n kinds[propertyKey] = kind;\n Reflect.defineMetadata(METADATA_KEYS.ENDPOINT_KIND, kinds, metadataTarget);\n\n const opts: Record<string, EndpointOptions> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_OPTIONS, metadataTarget) || {};\n opts[propertyKey] = options;\n Reflect.defineMetadata(METADATA_KEYS.ENDPOINT_OPTIONS, opts, metadataTarget);\n\n const declared = options as ExternalEndpointOptions;\n if (\n kind !== EXTERNAL ||\n typeof declared.calledBy !== 'string' ||\n declared.calledBy === ''\n )\n return;\n const callers: Record<string, ExternalCaller> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_CALLER, metadataTarget) || {};\n callers[propertyKey] = new ExternalCaller(\n declared.callerKind ?? DEFAULT_CALLER_KIND,\n declared.calledBy,\n );\n Reflect.defineMetadata(METADATA_KEYS.ENDPOINT_CALLER, callers, metadataTarget);\n}\n\n/** Declares request/response DTO field names that API logging must mask at any depth. */\n// webpieces-disable no-function-outside-class -- decorator factory; decorators are inherently module-scope\nexport function MaskLog(fields: Record<string, MaskMode>): MethodDecorator {\n const spec = new MaskSpec(fields);\n // webpieces-disable no-any-unknown -- reflect-metadata decorator API requires any\n return (target: any, propertyKey: string | symbol, _descriptor: PropertyDescriptor) => {\n const metadataTarget = typeof target === 'function' ? target : target.constructor;\n const specs: Record<string, MaskSpec> =\n Reflect.getMetadata(METADATA_KEYS.MASK_LOG, metadataTarget) || {};\n specs[propertyKey as string] = spec;\n Reflect.defineMetadata(METADATA_KEYS.MASK_LOG, specs, metadataTarget);\n };\n}\n\n/**\n * The @MaskLog spec for one method, or undefined if the method declared none (the common case — the\n * caller then logs the DTO verbatim on the plain JSON.stringify fast path).\n */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpointOptions\nexport function getMaskSpec(apiClass: Function, methodName: string): MaskSpec | undefined {\n const specs: Record<string, MaskSpec> =\n Reflect.getMetadata(METADATA_KEYS.MASK_LOG, apiClass) || {};\n return specs[methodName];\n}\n\n/**\n * Shared implementation for every auth decorator. Authorization is deliberately\n * method-only: a class-level default is too easy to miss when reviewing one endpoint.\n */\n// webpieces-disable no-function-outside-class -- decorator factory; decorators are inherently module-scope\nfunction defineAuthMetadata(authMeta: AuthMeta): MethodDecorator {\n\n // webpieces-disable no-any-unknown -- reflect-metadata decorator API requires any\n return (target: any, propertyKey?: string | symbol, _descriptor?: PropertyDescriptor) => {\n if (propertyKey === undefined) {\n throw new Error(\n 'Authorization decorators are method-only; annotate every @Endpoint explicitly.',\n );\n }\n const metadataTarget = typeof target === 'function' ? target : target.constructor;\n if (Reflect.hasMetadata('webpieces:ipc-api-id', metadataTarget)) {\n throw new Error(\n `Internal API ${metadataTarget.name || 'Unknown'} cannot use HTTP authorization decorators.`,\n );\n }\n validateNoConflictingDecorators(metadataTarget, propertyKey as string);\n Reflect.defineMetadata(METADATA_KEYS.AUTH_META, authMeta, metadataTarget, propertyKey);\n const methods = new Set<string>(\n Reflect.getMetadata(METADATA_KEYS.AUTH_METHODS, metadataTarget) || [],\n );\n methods.add(propertyKey as string);\n Reflect.defineMetadata(METADATA_KEYS.AUTH_METHODS, [...methods], metadataTarget);\n };\n}\n\n/**\n * @WpAuthPublic(reason) - endpoint intentionally requires no authentication.\n * The non-empty reason makes anonymous exposure an explicit review decision.\n */\n// webpieces-disable no-function-outside-class -- decorator factory; decorators are inherently module-scope\nexport function WpAuthPublic(reason: string): MethodDecorator {\n if (typeof reason !== 'string' || reason.trim() === '') {\n throw new Error(\n '@WpAuthPublic requires a non-empty reason explaining why anonymous access is required.',\n );\n }\n return defineAuthMetadata(new AuthMeta([{ kind: 'public' }], reason));\n}\n\n/** Protected network ingress: authenticate one declared credential, then authorize independently. */\n// webpieces-disable no-function-outside-class -- canonical method decorator factory\nexport function WpAuth(methods: AuthMethods): MethodDecorator {\n return defineAuthMetadata(new AuthMeta(methods, undefined));\n}\n\n/** Locality is independent of authentication and cannot prove a user or machine identity. */\n// webpieces-disable no-function-outside-class -- canonical method decorator factory\nexport function WpLocalOnly(): MethodDecorator {\n return (target: object, methodName: string | symbol) => {\n if (methodName === undefined) throw new Error('@WpLocalOnly is method-only.');\n Reflect.defineMetadata(METADATA_KEYS.LOCAL_ONLY, true, target.constructor, methodName);\n };\n}\n\n// webpieces-disable no-function-outside-class -- canonical metadata reader\nexport function isLocalOnly(apiClass: Function, methodName: string): boolean {\n return Reflect.getMetadata(METADATA_KEYS.LOCAL_ONLY, apiClass, methodName) === true;\n}\n\n// ============================================================\n// Helper functions\n// ============================================================\n\n/**\n * Get the base path from @ApiPath decorator.\n */\nexport function getApiPath(apiClass: Function): string | undefined {\n return Reflect.getMetadata(METADATA_KEYS.API_PATH, apiClass);\n}\n\n/**\n * Get all endpoints from @Endpoint decorators.\n * Returns a record of methodName -> endpoint path.\n */\nexport function getEndpoints(apiClass: Function): Record<string, string> | undefined {\n return Reflect.getMetadata(METADATA_KEYS.ENDPOINTS, apiClass);\n}\n\n/**\n * Every method's declared trigger kind, as `methodName -> kind`. Parallel to {@link getEndpoints}.\n * Empty for a class carrying no @Endpoint at all.\n */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpoints\nexport function getEndpointKinds(apiClass: Function): Record<string, EndpointKind> {\n return Reflect.getMetadata(METADATA_KEYS.ENDPOINT_KIND, apiClass) || {};\n}\n\n/**\n * What triggers ONE method, or undefined when the method carries no @Endpoint.\n *\n * Defaults to nothing rather than to 'rpc': `kind` is a required argument, so a missing entry means\n * \"this is not an endpoint\", never \"an endpoint that forgot to say\". Silently defaulting here would\n * put an undeclared cron or webhook back into the graph as a normal rpc call — the exact blindness\n * the required argument exists to remove.\n */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpoints\nexport function getEndpointKind(apiClass: Function, methodName: string): EndpointKind | undefined {\n return getEndpointKinds(apiClass)[methodName];\n}\n\n/** The required HTTP method for one endpoint. */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpointKind\nexport function getEndpointHttpMethod(apiClass: Function, methodName: string): HttpMethod {\n const methods: Record<string, HttpMethod> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_HTTP_METHOD, apiClass) || {};\n const method = methods[methodName];\n if (!isHttpMethod(method)) {\n throw new Error(\n `@Endpoint ${apiClass.name || 'Unknown'}.${methodName} must declare GET or POST.`,\n );\n }\n return method;\n}\n\n/**\n * Get the @Endpoint options for one method (empty object if the method had no options).\n */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpoints\nexport function getEndpointOptions(apiClass: Function, methodName: string): EndpointOptions {\n const opts: Record<string, EndpointOptions> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_OPTIONS, apiClass) || {};\n const options = opts[methodName];\n if (!options && getEndpoints(apiClass)?.[methodName] === undefined) {\n // Preserve the historical helper behavior for a method that is not an endpoint at all.\n return {} as EndpointOptions;\n }\n return options ?? {};\n}\n\n/** Read one endpoint's required side-effect semantics. */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpointOptions\nexport function getEndpointOperation(apiClass: Function, methodName: string): EndpointOperation {\n const operations: Record<string, EndpointOperation> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_OPERATION, apiClass) || {};\n const operation = operations[methodName];\n if (!isEndpointOperation(operation)) {\n throw new Error(\n `@Endpoint ${apiClass.name || 'Unknown'}.${methodName} must declare READ, ` +\n 'WRITE_IDEMPOTENT, or WRITE.',\n );\n }\n return operation;\n}\n\n// webpieces-disable no-function-outside-class -- runtime backstop for JavaScript and `as any` callers; webpieces-disable no-any-unknown -- untrusted runtime value is narrowed to an endpoint operation\nfunction isEndpointOperation(value: unknown): value is EndpointOperation {\n return (\n value === READ ||\n value === WRITE_IDEMPOTENT ||\n value === WRITE\n );\n}\n\n// webpieces-disable no-function-outside-class -- runtime backstop for JavaScript and `as any` callers; webpieces-disable no-any-unknown -- untrusted runtime value is narrowed to an HTTP method\nfunction isHttpMethod(value: unknown): value is HttpMethod {\n return value === GET || value === POST;\n}\n\n// webpieces-disable no-function-outside-class -- runtime backstop for JavaScript and `as any` callers; webpieces-disable no-any-unknown -- untrusted runtime value is narrowed to an endpoint kind\nfunction isEndpointKind(value: unknown): value is EndpointKind {\n return (\n value === RPC ||\n value === CLOUDTASKS ||\n value === CRON ||\n value === EXTERNAL\n );\n}\n\n/**\n * Fail-fast at wiring time when an `external` endpoint declared no caller. The {@link Endpoint}\n * overloads already make that a COMPILE error; this is the backstop for the ways TS is bypassed —\n * a JS caller, an `as any` options object, a hand-rolled Reflect.defineMetadata.\n * @throws Error naming the first external endpoint with no `calledBy`.\n */\n// webpieces-disable no-function-outside-class -- wiring-time assert, sibling of assertEveryEndpointHasAuthMode\nexport function assertEveryExternalEndpointDeclaresCaller(apiClass: Function): void {\n const kinds = getEndpointKinds(apiClass);\n for (const methodName of Object.keys(kinds)) {\n if (\n kinds[methodName] !== 'external' ||\n getEndpointCaller(apiClass, methodName) !== undefined\n )\n continue;\n throw new Error(\n `External endpoint '${methodName}' in ${apiClass.name || 'Unknown'} declares no caller. Say WHO ` +\n `posts to it: @Endpoint(POST, path, WRITE, EXTERNAL, { calledBy: '<vendor>' }) — the runtime architecture ` +\n `graph cannot name an inbound caller it was never told about.`,\n );\n }\n}\n\n/**\n * True when the method's @Endpoint declared `{ formPost: true }` — its body is\n * application/x-www-form-urlencoded (flat), not JSON.\n */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpoints\nexport function isFormPost(apiClass: Function, methodName: string): boolean {\n return getEndpointOptions(apiClass, methodName).formPost === true;\n}\n\n/**\n * True when the method's @Endpoint declared `{ rawBody: true }` — the transport must retain the\n * verbatim bytes + absolute url for an {@link WebhookAuthCallback} hook to verify.\n */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of isFormPost\nexport function isRawBody(apiClass: Function, methodName: string): boolean {\n return getEndpointOptions(apiClass, methodName).rawBody === true;\n}\n\n/**\n * Fail-fast at wiring time when an `webhook(...)` endpoint did not ask the transport to keep the\n * bytes it is supposed to verify. A hook with nothing to verify is a MISCONFIGURATION, and it must\n * surface at startup, naming the fix — not as a 401 in production on exactly the traffic the endpoint\n * exists for.\n *\n * This pairing is a runtime assert rather than a type because the two halves live on DIFFERENT\n * decorators (`webhook(...)` and `@Endpoint`), and no union over one decorator's argument can say\n * anything about the other's.\n *\n * @throws Error naming the first `webhook(...)` endpoint missing `{ rawBody: true }`.\n */\n// webpieces-disable no-function-outside-class -- wiring-time assert, sibling of assertEveryEndpointHasAuthMode\nexport function assertEveryWebhookEndpointRetainsRawBody(apiClass: Function): void {\n const endpoints = getEndpoints(apiClass) || {};\n for (const methodName of Object.keys(endpoints)) {\n if (\n !getAuthMeta(apiClass, methodName)?.methods.some((method: AuthMode) => method.kind === 'webhook') ||\n isRawBody(apiClass, methodName)\n )\n continue;\n throw new Error(\n `Endpoint '${methodName}' in ${apiClass.name || 'Unknown'} is webhook(...) but its @Endpoint ` +\n `does not declare { rawBody: true }. A webhook hook verifies a signature over the bytes and ` +\n `the url the SENDER transmitted, and without that option the transport parses the body and ` +\n `throws them away — leaving the hook nothing to check.`,\n );\n }\n}\n\n/**\n * Check if a class has @ApiPath decorator.\n */\nexport function isApiPath(apiClass: Function): boolean {\n return Reflect.hasMetadata(METADATA_KEYS.API_PATH, apiClass);\n}\n\n/**\n * Get method-level auth metadata. Class-level authorization is forbidden.\n */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader paired with the decorator API\nexport function getAuthMeta(apiClass: Function, methodName: string): AuthMeta | undefined {\n return Reflect.getMetadata(METADATA_KEYS.AUTH_META, apiClass, methodName);\n}\n\n/**\n * The ONE prescription for \"this endpoint declares no auth\", shared by the two places that raise it\n * (here and http-routing's ApiRoutingFactory) because they had drifted into teaching different menus.\n * A message teaching an incomplete API is the same defect as an API with two spellings: whichever menu\n * the caller hits becomes the API they believe exists. It leads with the ROLE-GATED member on purpose —\n * the first thing offered should not be the widest grant.\n */\nexport const MISSING_AUTH_DECORATOR_FIX =\n \"Declare @WpAuth([jwt(), oidc(...callers), sharedSecret(key), webhook(name), apiKey('regime', [{in: 'header', key: MyKeys.API_KEY}])]) \" +\n \"or @WpAuthPublic('reason'), and exactly one @WpAuthorization on every endpoint. Add @WpLocalOnly() separately when locality is required.\";\n\n/**\n * Fail-fast at wiring time if any endpoint lacks an auth mode. Both the server\n * (ApiRoutingFactory) and the task/rpc clients call this so a missing auth\n * decorator is a startup error, never a silent open endpoint.\n * @throws Error naming the first endpoint with no auth decorator, via {@link MISSING_AUTH_DECORATOR_FIX}.\n */\nexport function assertEveryEndpointHasAuthMode(apiClass: Function): void {\n const apiName = apiClass.name || 'Unknown';\n const endpoints = getEndpoints(apiClass) || {};\n for (const methodName of Object.keys(endpoints)) {\n if (!getAuthMeta(apiClass, methodName)) {\n throw new Error(\n `Endpoint '${methodName}' in ${apiName} has no auth decorator. ` +\n MISSING_AUTH_DECORATOR_FIX,\n );\n }\n const policy = getAuthorization(apiClass, methodName);\n if (!policy) throw new Error(`Endpoint '${methodName}' in ${apiName} requires @WpAuthorization.`);\n AuthorizationDeclaration.validate(policy);\n const auth = getAuthMeta(apiClass, methodName)!;\n const isPublic = auth.methods.some((method: AuthMode) => method.kind === 'public');\n if (isPublic !== (policy.authType === AuthorizationType.ANONYMOUS)) {\n throw new Error(`Endpoint '${methodName}' must pair public authentication with ANONYMOUS authorization, or protected authentication with protected/CUSTOM authorization.`);\n }\n }\n const policyMethods: string[] = Reflect.getMetadata(AUTHORIZATION_METHODS_KEY, apiClass) ?? [];\n for (const methodName of policyMethods) {\n if (!(methodName in endpoints)) throw new Error(`Orphan @WpAuthorization on ${apiName}.${methodName}; declare @Endpoint.`);\n }\n}\n\n/**\n * Validate that a class/method doesn't have conflicting auth decorators.\n * @throws Error if multiple auth decorators are found on the same target.\n */\n// webpieces-disable no-function-outside-class -- shared decorator metadata validation\nexport function validateNoConflictingDecorators(\n apiClass: Function,\n methodName: string | undefined,\n): void {\n const existing = methodName\n ? Reflect.getMetadata(METADATA_KEYS.AUTH_META, apiClass, methodName)\n : Reflect.getMetadata(METADATA_KEYS.AUTH_META, apiClass);\n\n if (existing) {\n const targetName = apiClass.name || 'Unknown';\n const location = methodName\n ? `method '${methodName}' of ${targetName}`\n : `class ${targetName}`;\n throw new Error(\n `Conflicting auth decorator on ${location}. ` +\n `Exactly one @WpAuth([...]) or @WpAuthPublic('reason') is allowed per endpoint.`,\n );\n }\n}\n"]}
1
+ {"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../../../../../packages/core/core-util/src/http/decorators.ts"],"names":[],"mappings":"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","sourcesContent":["import 'reflect-metadata';\nimport { MaskSpec, MaskMode } from './LogFieldMask';\nimport {\n DEFAULT_CALLER_KIND,\n ENDPOINT_CALLER_KEY,\n ExternalCaller,\n getEndpointCaller,\n} from './external-caller';\n// The TYPE layer these decorators attach — split out for file size only (see auth-mode.ts).\nimport { AuthMeta, AuthMethods, AuthMode } from './auth-mode';\nimport {\n EndpointOperation,\n EndpointOptions,\n ExternalEndpointOptions,\n READ,\n WRITE_IDEMPOTENT,\n WRITE,\n} from './HttpEndpointOptions';\nimport { GET, HttpMethod, POST } from './HttpContract';\nimport { AuthorizationDeclaration, AuthorizationType, AUTHORIZATION_METHODS_KEY, getAuthorization } from './authorization';\nimport { HTTP_PARAMETERS_METADATA_KEY } from './http-parameter-decorators';\n\nexport type { EndpointOptions, ExternalEndpointOptions } from './HttpEndpointOptions';\nexport type { EndpointOperation } from './HttpEndpointOptions';\nexport { READ, WRITE_IDEMPOTENT, WRITE } from './HttpEndpointOptions';\nexport type { HttpMethod } from './HttpContract';\nexport { GET, POST } from './HttpContract';\nexport { PathParam, QueryParam, getHttpParameterDeclarations } from './http-parameter-decorators';\n\n/**\n * Metadata keys for storing API routing information.\n * These keys are used by both server-side (routing) and client-side (client generation).\n */\nexport const METADATA_KEYS = {\n API_PATH: 'webpieces:api-path',\n ENDPOINTS: 'webpieces:endpoints',\n AUTH_META: 'webpieces:auth-meta',\n /** Method names carrying one of the canonical authorization decorators. */\n AUTH_METHODS: 'webpieces:auth-methods',\n /** 'rpc' (default, sync request/response) vs 'pubsub' (fire-and-forget cloud task). */\n API_KIND: 'webpieces:api-kind',\n /** Per-method Cloud Tasks queue-name override (set via @Queue). */\n QUEUE_OVERRIDE: 'webpieces:queue-override',\n /** Per-method @Endpoint options (e.g. formPost), parallel to ENDPOINTS. */\n ENDPOINT_OPTIONS: 'webpieces:endpoint-options',\n /** Per-method required HTTP method, parallel to ENDPOINTS. */\n ENDPOINT_HTTP_METHOD: 'webpieces:endpoint-http-method',\n /** Per-method required read/write semantics, parallel to ENDPOINTS. */\n ENDPOINT_OPERATION: 'webpieces:endpoint-operation',\n /** Per-method @Endpoint trigger kind (rpc | cloudtasks | cron | external), parallel to ENDPOINTS. */\n ENDPOINT_KIND: 'webpieces:endpoint-kind',\n /** Per-method declared external CALLER (only for kind 'external'), parallel to ENDPOINTS. */\n ENDPOINT_CALLER: ENDPOINT_CALLER_KEY,\n /** Per-method @MaskLog spec (which DTO fields the LogApiCall path masks). */\n MASK_LOG: 'webpieces:mask-log',\n /** Per-method opt-in metadata for publishing an RPC endpoint as an MCP tool. */\n MCP_TOOLS: 'webpieces:mcp-tools',\n /** Per-method PERMANENT exclusion from MCP, with the reason — see @InvalidEndpointForMcp. */\n MCP_INVALID: 'webpieces:mcp-invalid',\n /** Per-method request/response event metadata for a typed streaming endpoint. */\n STREAM_ENDPOINTS: 'webpieces:stream-endpoints',\n /** Per-method MCP-user authorization, intentionally separate from HTTP hop auth. */\n LOCAL_ONLY: 'webpieces:local-only',\n /** Per-method explicit path/query parameter declarations, keyed by parameter index. */\n HTTP_PARAMETERS: HTTP_PARAMETERS_METADATA_KEY,\n};\n\n/** Nominal backing keeps raw string literals out of endpoint declarations. */\nenum EndpointKindValue {\n RPC = 'rpc',\n CLOUDTASKS = 'cloudtasks',\n CRON = 'cron',\n EXTERNAL = 'external',\n}\n\n/** Short, statically importable decorator arguments. */\nexport const RPC = EndpointKindValue.RPC;\nexport const CLOUDTASKS = EndpointKindValue.CLOUDTASKS;\nexport const CRON = EndpointKindValue.CRON;\nexport const EXTERNAL = EndpointKindValue.EXTERNAL;\n\n/** Runtime trigger/delivery owner used by validation, architecture, and infrastructure tooling. */\nexport type EndpointKind = typeof RPC | typeof CLOUDTASKS | typeof CRON | typeof EXTERNAL;\n\n/** Class decorator that sets the shared base path for all endpoints. */\nexport function ApiPath(basePath: string): ClassDecorator {\n return (target: Function) => {\n if (Reflect.hasMetadata('webpieces:ipc-api-id', target)) {\n throw new Error(\n `Class ${target.name || 'Unknown'} cannot combine @ApiPath with @WpInternal.`,\n );\n }\n Reflect.defineMetadata(METADATA_KEYS.API_PATH, basePath, target);\n\n // Initialize endpoints map if not exists\n if (!Reflect.hasMetadata(METADATA_KEYS.ENDPOINTS, target)) {\n Reflect.defineMetadata(METADATA_KEYS.ENDPOINTS, {}, target);\n }\n };\n}\n\n/**\n * Registers `@Endpoint(POST, path, WRITE, RPC)`. Method, operation, and trigger are required enum\n * values. Operation is independent of the HTTP verb. EXTERNAL additionally requires `calledBy`.\n * Each classification rides a parallel metadata map while ENDPOINTS remains method-name -> path.\n */\n// webpieces-disable no-function-outside-class -- decorator factory; decorators are inherently module-scope\nexport function Endpoint(\n httpMethod: HttpMethod,\n path: string,\n operation: EndpointOperation,\n kind: typeof EXTERNAL,\n options: ExternalEndpointOptions,\n): MethodDecorator;\n// webpieces-disable no-function-outside-class -- decorator factory; decorators are inherently module-scope\nexport function Endpoint(\n httpMethod: HttpMethod,\n path: string,\n operation: EndpointOperation,\n kind: Exclude<EndpointKind, typeof EXTERNAL>,\n options?: EndpointOptions,\n): MethodDecorator;\n// webpieces-disable no-function-outside-class -- decorator factory; decorators are inherently module-scope\nexport function Endpoint(\n httpMethod: HttpMethod,\n path: string,\n operation: EndpointOperation,\n kind: EndpointKind,\n options: EndpointOptions = {},\n): MethodDecorator {\n validateEndpointClassification(httpMethod, operation, kind);\n // webpieces-disable no-any-unknown -- reflect-metadata decorator API requires any\n return (target: any, propertyKey: string | symbol, _descriptor: PropertyDescriptor) => {\n const metadataTarget = typeof target === 'function' ? target : target.constructor;\n recordEndpointMetadata(\n metadataTarget,\n propertyKey as string,\n httpMethod,\n path,\n operation,\n kind,\n options,\n );\n };\n}\n\n// webpieces-disable no-function-outside-class -- runtime validation backs up nominal TS enums\nfunction validateEndpointClassification(\n httpMethod: HttpMethod,\n operation: EndpointOperation,\n kind: EndpointKind,\n): void {\n if (!isHttpMethod(httpMethod)) {\n throw new Error(\n `@Endpoint httpMethod must be GET or POST, received '${String(httpMethod)}'.`,\n );\n }\n if (!isEndpointOperation(operation)) {\n throw new Error(\n `@Endpoint operation must be READ, WRITE_IDEMPOTENT, or WRITE, received '${String(operation)}'.`,\n );\n }\n if (!isEndpointKind(kind)) {\n throw new Error(\n `@Endpoint trigger must be RPC, CLOUDTASKS, CRON, or EXTERNAL, received '${String(kind)}'.`,\n );\n }\n}\n\n// webpieces-disable no-function-outside-class -- one metadata write shared by the decorator overloads\nfunction recordEndpointMetadata(\n metadataTarget: Function,\n propertyKey: string,\n httpMethod: HttpMethod,\n path: string,\n operation: EndpointOperation,\n kind: EndpointKind,\n options: EndpointOptions,\n): void {\n const endpoints: Record<string, string> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINTS, metadataTarget) || {};\n\n endpoints[propertyKey] = path;\n\n Reflect.defineMetadata(METADATA_KEYS.ENDPOINTS, endpoints, metadataTarget);\n\n const methods: Record<string, HttpMethod> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_HTTP_METHOD, metadataTarget) || {};\n methods[propertyKey] = httpMethod;\n Reflect.defineMetadata(METADATA_KEYS.ENDPOINT_HTTP_METHOD, methods, metadataTarget);\n\n const operations: Record<string, EndpointOperation> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_OPERATION, metadataTarget) || {};\n operations[propertyKey] = operation;\n Reflect.defineMetadata(METADATA_KEYS.ENDPOINT_OPERATION, operations, metadataTarget);\n\n const kinds: Record<string, EndpointKind> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_KIND, metadataTarget) || {};\n kinds[propertyKey] = kind;\n Reflect.defineMetadata(METADATA_KEYS.ENDPOINT_KIND, kinds, metadataTarget);\n\n const opts: Record<string, EndpointOptions> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_OPTIONS, metadataTarget) || {};\n opts[propertyKey] = options;\n Reflect.defineMetadata(METADATA_KEYS.ENDPOINT_OPTIONS, opts, metadataTarget);\n\n const declared = options as ExternalEndpointOptions;\n if (\n kind !== EXTERNAL ||\n typeof declared.calledBy !== 'string' ||\n declared.calledBy === ''\n )\n return;\n const callers: Record<string, ExternalCaller> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_CALLER, metadataTarget) || {};\n callers[propertyKey] = new ExternalCaller(\n declared.callerKind ?? DEFAULT_CALLER_KIND,\n declared.calledBy,\n );\n Reflect.defineMetadata(METADATA_KEYS.ENDPOINT_CALLER, callers, metadataTarget);\n}\n\n/** Declares request/response DTO field names that API logging must mask at any depth. */\n// webpieces-disable no-function-outside-class -- decorator factory; decorators are inherently module-scope\nexport function MaskLog(fields: Record<string, MaskMode>): MethodDecorator {\n const spec = new MaskSpec(fields);\n // webpieces-disable no-any-unknown -- reflect-metadata decorator API requires any\n return (target: any, propertyKey: string | symbol, _descriptor: PropertyDescriptor) => {\n const metadataTarget = typeof target === 'function' ? target : target.constructor;\n const specs: Record<string, MaskSpec> =\n Reflect.getMetadata(METADATA_KEYS.MASK_LOG, metadataTarget) || {};\n specs[propertyKey as string] = spec;\n Reflect.defineMetadata(METADATA_KEYS.MASK_LOG, specs, metadataTarget);\n };\n}\n\n/**\n * The @MaskLog spec for one method, or undefined if the method declared none (the common case — the\n * caller then logs the DTO verbatim on the plain JSON.stringify fast path).\n */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpointOptions\nexport function getMaskSpec(apiClass: Function, methodName: string): MaskSpec | undefined {\n const specs: Record<string, MaskSpec> =\n Reflect.getMetadata(METADATA_KEYS.MASK_LOG, apiClass) || {};\n return specs[methodName];\n}\n\n/**\n * Shared implementation for every auth decorator. Authorization is deliberately\n * method-only: a class-level default is too easy to miss when reviewing one endpoint.\n */\n// webpieces-disable no-function-outside-class -- decorator factory; decorators are inherently module-scope\nfunction defineAuthMetadata(authMeta: AuthMeta): MethodDecorator {\n\n // webpieces-disable no-any-unknown -- reflect-metadata decorator API requires any\n return (target: any, propertyKey?: string | symbol, _descriptor?: PropertyDescriptor) => {\n if (propertyKey === undefined) {\n throw new Error(\n 'Authorization decorators are method-only; annotate every @Endpoint explicitly.',\n );\n }\n const metadataTarget = typeof target === 'function' ? target : target.constructor;\n if (Reflect.hasMetadata('webpieces:ipc-api-id', metadataTarget)) {\n throw new Error(\n `Internal API ${metadataTarget.name || 'Unknown'} cannot use HTTP authorization decorators.`,\n );\n }\n validateNoConflictingDecorators(metadataTarget, propertyKey as string);\n Reflect.defineMetadata(METADATA_KEYS.AUTH_META, authMeta, metadataTarget, propertyKey);\n const methods = new Set<string>(\n Reflect.getMetadata(METADATA_KEYS.AUTH_METHODS, metadataTarget) || [],\n );\n methods.add(propertyKey as string);\n Reflect.defineMetadata(METADATA_KEYS.AUTH_METHODS, [...methods], metadataTarget);\n };\n}\n\n/**\n * @WpAuthPublic(reason) - endpoint intentionally requires no authentication.\n * The non-empty reason makes anonymous exposure an explicit review decision.\n */\n// webpieces-disable no-function-outside-class -- decorator factory; decorators are inherently module-scope\nexport function WpAuthPublic(reason: string): MethodDecorator {\n if (typeof reason !== 'string' || reason.trim() === '') {\n throw new Error(\n '@WpAuthPublic requires a non-empty reason explaining why anonymous access is required.',\n );\n }\n return defineAuthMetadata(new AuthMeta([{ kind: 'public' }], reason));\n}\n\n/** Protected network ingress: authenticate one declared credential, then authorize independently. */\n// webpieces-disable no-function-outside-class -- canonical method decorator factory\nexport function WpAuth(methods: AuthMethods): MethodDecorator {\n return defineAuthMetadata(new AuthMeta(methods, undefined));\n}\n\n/** Locality is independent of authentication and cannot prove a user or machine identity. */\n// webpieces-disable no-function-outside-class -- canonical method decorator factory\nexport function WpLocalOnly(): MethodDecorator {\n return (target: object, methodName: string | symbol) => {\n if (methodName === undefined) throw new Error('@WpLocalOnly is method-only.');\n Reflect.defineMetadata(METADATA_KEYS.LOCAL_ONLY, true, target.constructor, methodName);\n };\n}\n\n// webpieces-disable no-function-outside-class -- canonical metadata reader\nexport function isLocalOnly(apiClass: Function, methodName: string): boolean {\n return Reflect.getMetadata(METADATA_KEYS.LOCAL_ONLY, apiClass, methodName) === true;\n}\n\n// ============================================================\n// Helper functions\n// ============================================================\n\n/**\n * Get the base path from @ApiPath decorator.\n */\nexport function getApiPath(apiClass: Function): string | undefined {\n return Reflect.getMetadata(METADATA_KEYS.API_PATH, apiClass);\n}\n\n/**\n * Get all endpoints from @Endpoint decorators.\n * Returns a record of methodName -> endpoint path.\n */\nexport function getEndpoints(apiClass: Function): Record<string, string> | undefined {\n return Reflect.getMetadata(METADATA_KEYS.ENDPOINTS, apiClass);\n}\n\n/**\n * Every method's declared trigger kind, as `methodName -> kind`. Parallel to {@link getEndpoints}.\n * Empty for a class carrying no @Endpoint at all.\n */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpoints\nexport function getEndpointKinds(apiClass: Function): Record<string, EndpointKind> {\n return Reflect.getMetadata(METADATA_KEYS.ENDPOINT_KIND, apiClass) || {};\n}\n\n/**\n * What triggers ONE method, or undefined when the method carries no @Endpoint.\n *\n * Defaults to nothing rather than to 'rpc': `kind` is a required argument, so a missing entry means\n * \"this is not an endpoint\", never \"an endpoint that forgot to say\". Silently defaulting here would\n * put an undeclared cron or webhook back into the graph as a normal rpc call — the exact blindness\n * the required argument exists to remove.\n */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpoints\nexport function getEndpointKind(apiClass: Function, methodName: string): EndpointKind | undefined {\n return getEndpointKinds(apiClass)[methodName];\n}\n\n/** The required HTTP method for one endpoint. */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpointKind\nexport function getEndpointHttpMethod(apiClass: Function, methodName: string): HttpMethod {\n const methods: Record<string, HttpMethod> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_HTTP_METHOD, apiClass) || {};\n const method = methods[methodName];\n if (!isHttpMethod(method)) {\n throw new Error(\n `@Endpoint ${apiClass.name || 'Unknown'}.${methodName} must declare GET or POST.`,\n );\n }\n return method;\n}\n\n/**\n * Get the @Endpoint options for one method (empty object if the method had no options).\n */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpoints\nexport function getEndpointOptions(apiClass: Function, methodName: string): EndpointOptions {\n const opts: Record<string, EndpointOptions> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_OPTIONS, apiClass) || {};\n const options = opts[methodName];\n if (!options && getEndpoints(apiClass)?.[methodName] === undefined) {\n // Preserve the historical helper behavior for a method that is not an endpoint at all.\n return {} as EndpointOptions;\n }\n return options ?? {};\n}\n\n/** Read one endpoint's required side-effect semantics. */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpointOptions\nexport function getEndpointOperation(apiClass: Function, methodName: string): EndpointOperation {\n const operations: Record<string, EndpointOperation> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_OPERATION, apiClass) || {};\n const operation = operations[methodName];\n if (!isEndpointOperation(operation)) {\n throw new Error(\n `@Endpoint ${apiClass.name || 'Unknown'}.${methodName} must declare READ, ` +\n 'WRITE_IDEMPOTENT, or WRITE.',\n );\n }\n return operation;\n}\n\n// webpieces-disable no-function-outside-class -- runtime backstop for JavaScript and `as any` callers; webpieces-disable no-any-unknown -- untrusted runtime value is narrowed to an endpoint operation\nfunction isEndpointOperation(value: unknown): value is EndpointOperation {\n return (\n value === READ ||\n value === WRITE_IDEMPOTENT ||\n value === WRITE\n );\n}\n\n// webpieces-disable no-function-outside-class -- runtime backstop for JavaScript and `as any` callers; webpieces-disable no-any-unknown -- untrusted runtime value is narrowed to an HTTP method\nfunction isHttpMethod(value: unknown): value is HttpMethod {\n return value === GET || value === POST;\n}\n\n// webpieces-disable no-function-outside-class -- runtime backstop for JavaScript and `as any` callers; webpieces-disable no-any-unknown -- untrusted runtime value is narrowed to an endpoint kind\nfunction isEndpointKind(value: unknown): value is EndpointKind {\n return (\n value === RPC ||\n value === CLOUDTASKS ||\n value === CRON ||\n value === EXTERNAL\n );\n}\n\n/**\n * Fail-fast at wiring time when an `external` endpoint declared no caller. The {@link Endpoint}\n * overloads already make that a COMPILE error; this is the backstop for the ways TS is bypassed —\n * a JS caller, an `as any` options object, a hand-rolled Reflect.defineMetadata.\n * @throws Error naming the first external endpoint with no `calledBy`.\n */\n// webpieces-disable no-function-outside-class -- wiring-time assert, sibling of assertEveryEndpointHasAuthMode\nexport function assertEveryExternalEndpointDeclaresCaller(apiClass: Function): void {\n const kinds = getEndpointKinds(apiClass);\n for (const methodName of Object.keys(kinds)) {\n if (\n kinds[methodName] !== 'external' ||\n getEndpointCaller(apiClass, methodName) !== undefined\n )\n continue;\n throw new Error(\n `External endpoint '${methodName}' in ${apiClass.name || 'Unknown'} declares no caller. Say WHO ` +\n `posts to it: @Endpoint(POST, path, WRITE, EXTERNAL, { calledBy: '<vendor>' }) — the runtime architecture ` +\n `graph cannot name an inbound caller it was never told about.`,\n );\n }\n}\n\n/**\n * True when the method's @Endpoint declared `{ formPost: true }` — its body is\n * application/x-www-form-urlencoded (flat), not JSON.\n */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpoints\nexport function isFormPost(apiClass: Function, methodName: string): boolean {\n return getEndpointOptions(apiClass, methodName).formPost === true;\n}\n\n/**\n * True when the method's @Endpoint declared `{ rawBody: true }` — the transport must retain the\n * verbatim bytes + absolute url for an {@link WebhookAuthCallback} hook to verify.\n */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of isFormPost\nexport function isRawBody(apiClass: Function, methodName: string): boolean {\n return getEndpointOptions(apiClass, methodName).rawBody === true;\n}\n\n/**\n * Fail-fast at wiring time when an `webhook(...)` endpoint did not ask the transport to keep the\n * bytes it is supposed to verify. A hook with nothing to verify is a MISCONFIGURATION, and it must\n * surface at startup, naming the fix — not as a 401 in production on exactly the traffic the endpoint\n * exists for.\n *\n * This pairing is a runtime assert rather than a type because the two halves live on DIFFERENT\n * decorators (`webhook(...)` and `@Endpoint`), and no union over one decorator's argument can say\n * anything about the other's.\n *\n * @throws Error naming the first `webhook(...)` endpoint missing `{ rawBody: true }`.\n */\n// webpieces-disable no-function-outside-class -- wiring-time assert, sibling of assertEveryEndpointHasAuthMode\nexport function assertEveryWebhookEndpointRetainsRawBody(apiClass: Function): void {\n const endpoints = getEndpoints(apiClass) || {};\n for (const methodName of Object.keys(endpoints)) {\n if (\n !getAuthMeta(apiClass, methodName)?.methods.some((method: AuthMode) => method.kind === 'webhook') ||\n isRawBody(apiClass, methodName)\n )\n continue;\n throw new Error(\n `Endpoint '${methodName}' in ${apiClass.name || 'Unknown'} is webhook(...) but its @Endpoint ` +\n `does not declare { rawBody: true }. A webhook hook verifies a signature over the bytes and ` +\n `the url the SENDER transmitted, and without that option the transport parses the body and ` +\n `throws them away — leaving the hook nothing to check.`,\n );\n }\n}\n\n/**\n * Check if a class has @ApiPath decorator.\n */\nexport function isApiPath(apiClass: Function): boolean {\n return Reflect.hasMetadata(METADATA_KEYS.API_PATH, apiClass);\n}\n\n/**\n * Get method-level auth metadata. Class-level authorization is forbidden.\n */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader paired with the decorator API\nexport function getAuthMeta(apiClass: Function, methodName: string): AuthMeta | undefined {\n return Reflect.getMetadata(METADATA_KEYS.AUTH_META, apiClass, methodName);\n}\n\n/**\n * The ONE prescription for \"this endpoint declares no auth\", shared by the two places that raise it\n * (here and http-routing's ApiRoutingFactory) because they had drifted into teaching different menus.\n * A message teaching an incomplete API is the same defect as an API with two spellings: whichever menu\n * the caller hits becomes the API they believe exists. It leads with the ROLE-GATED member on purpose —\n * the first thing offered should not be the widest grant.\n */\nexport const MISSING_AUTH_DECORATOR_FIX =\n \"Declare @WpAuth([jwt(), oidcSameProject() or oidcSvcs(['svc-a']), sharedSecret(key), webhook(name), apiKey('regime', [{in: 'header', key: MyKeys.API_KEY}])]) \" +\n \"or @WpAuthPublic('reason'), and exactly one @WpAuthorization on every endpoint. Add @WpLocalOnly() separately when locality is required.\";\n\n/**\n * Fail-fast at wiring time if any endpoint lacks an auth mode. Both the server\n * (ApiRoutingFactory) and the task/rpc clients call this so a missing auth\n * decorator is a startup error, never a silent open endpoint.\n * @throws Error naming the first endpoint with no auth decorator, via {@link MISSING_AUTH_DECORATOR_FIX}.\n */\nexport function assertEveryEndpointHasAuthMode(apiClass: Function): void {\n const apiName = apiClass.name || 'Unknown';\n const endpoints = getEndpoints(apiClass) || {};\n for (const methodName of Object.keys(endpoints)) {\n if (!getAuthMeta(apiClass, methodName)) {\n throw new Error(\n `Endpoint '${methodName}' in ${apiName} has no auth decorator. ` +\n MISSING_AUTH_DECORATOR_FIX,\n );\n }\n const policy = getAuthorization(apiClass, methodName);\n if (!policy) throw new Error(`Endpoint '${methodName}' in ${apiName} requires @WpAuthorization.`);\n AuthorizationDeclaration.validate(policy);\n const auth = getAuthMeta(apiClass, methodName)!;\n const isPublic = auth.methods.some((method: AuthMode) => method.kind === 'public');\n if (isPublic !== (policy.authType === AuthorizationType.ANONYMOUS)) {\n throw new Error(`Endpoint '${methodName}' must pair public authentication with ANONYMOUS authorization, or protected authentication with protected/CUSTOM authorization.`);\n }\n }\n const policyMethods: string[] = Reflect.getMetadata(AUTHORIZATION_METHODS_KEY, apiClass) ?? [];\n for (const methodName of policyMethods) {\n if (!(methodName in endpoints)) throw new Error(`Orphan @WpAuthorization on ${apiName}.${methodName}; declare @Endpoint.`);\n }\n}\n\n/**\n * Validate that a class/method doesn't have conflicting auth decorators.\n * @throws Error if multiple auth decorators are found on the same target.\n */\n// webpieces-disable no-function-outside-class -- shared decorator metadata validation\nexport function validateNoConflictingDecorators(\n apiClass: Function,\n methodName: string | undefined,\n): void {\n const existing = methodName\n ? Reflect.getMetadata(METADATA_KEYS.AUTH_META, apiClass, methodName)\n : Reflect.getMetadata(METADATA_KEYS.AUTH_META, apiClass);\n\n if (existing) {\n const targetName = apiClass.name || 'Unknown';\n const location = methodName\n ? `method '${methodName}' of ${targetName}`\n : `class ${targetName}`;\n throw new Error(\n `Conflicting auth decorator on ${location}. ` +\n `Exactly one @WpAuth([...]) or @WpAuthPublic('reason') is allowed per endpoint.`,\n );\n }\n}\n"]}
package/src/index.d.ts CHANGED
@@ -45,8 +45,8 @@ export type { ApiJsonSchemaType, DtoValue } from './mcp/DtoSchema';
45
45
  export { McpToolCatalogFile, McpToolCatalogError, McpToolDefinition, } from './mcp/McpToolCatalogFile';
46
46
  export { GeneratedApiDocsLayout, GenerateLayoutProblem, GenerateOutputLookup, GenerateOutputTarget, } from './mcp/GeneratedApiDocsLayout';
47
47
  export type { LayoutDependsOn, LayoutDependsOnObject, LayoutTarget, LayoutTargets, } from './mcp/GeneratedApiDocsLayout';
48
- export { AuthMeta, AuthDeclaration, jwt, oidc, sharedSecret, webhook, apiKey } from './http/auth-mode';
49
- export type { AuthMode, ApiKeyCredential, ApiKeyCredentials, AuthMethod, AuthMethods, } from './http/auth-mode';
48
+ export { AuthMeta, AuthDeclaration, jwt, oidcSameProject, oidcSvcs, sharedSecret, webhook, apiKey } from './http/auth-mode';
49
+ export type { AuthMode, ApiKeyCredential, ApiKeyCredentials, AuthMethod, AuthMethods, OidcAuthMethod, OidcAuthMethods, OidcCallers, } from './http/auth-mode';
50
50
  export { Rpc, PubSub, Queue, ENDPOINT_KINDS_BY_API_KIND, getApiKind, assertApiKind, assertPubSubConventions, getQueueName, } from './http/api-kind';
51
51
  export type { ApiKind } from './http/api-kind';
52
52
  export { EXTERNAL_SYSTEM_KINDS, DEFAULT_CALLER_KIND, ExternalCaller, isExternalSystemKind, getEndpointCaller, } from './http/external-caller';
package/src/index.js CHANGED
@@ -10,9 +10,9 @@
10
10
  Object.defineProperty(exports, "__esModule", { value: true });
11
11
  exports.MCP = exports.EXTERNAL_CUSTOMER = exports.SVC_TO_SVC = exports.ApiType = exports.NUMERIC_METADATA_KEYS = exports.WpMax = exports.WpMin = exports.WpInt = exports.getHttpParameterDeclarations = exports.QueryParam = exports.PathParam = exports.METADATA_KEYS = exports.validateNoConflictingDecorators = exports.assertEveryWebhookEndpointRetainsRawBody = exports.assertEveryExternalEndpointDeclaresCaller = exports.assertEveryEndpointHasAuthMode = exports.getAuthMeta = exports.isApiPath = exports.isRawBody = exports.isFormPost = exports.getMaskSpec = exports.getEndpointKinds = exports.getEndpointKind = exports.getEndpointOperation = exports.getEndpointOptions = exports.getEndpointHttpMethod = exports.getEndpoints = exports.getApiPath = exports.MaskLog = exports.isLocalOnly = exports.WpLocalOnly = exports.MISSING_AUTH_DECORATOR_FIX = exports.WpAuth = exports.WpAuthPublic = exports.Endpoint = exports.ApiPath = exports.GCP_LOG_BUDGET_BYTES = exports.MAX_GCP_LOG_BYTES = exports.LogChunkInfo = exports.LogChunkerImpl = exports.LogChunker = exports.LogManager = exports.ConsoleLoggerFactory = exports.ConsoleLogger = exports.DESIGN_METADATA_KEYS = exports.isDocumentDesign = exports.DocumentDesign = exports.ContextTuple = exports.ContextKey = exports.toError = void 0;
12
12
  exports.InvalidEndpointForMcp = exports.WRITE = exports.WRITE_IDEMPOTENT = exports.READ = exports.EXTERNAL = exports.CRON = exports.CLOUDTASKS = exports.RPC = exports.POST = exports.GET = exports.registerStreamingSchemas = exports.getStreamingEndpoint = exports.WpStream = exports.StreamDirection = exports.StreamWriter = exports.StreamTransportError = exports.StreamEventValidator = exports.StreamingEndpointMetadata = exports.StreamEnvelope = exports.StreamCorrelation = exports.HttpParameterDeclaration = exports.HttpParameterBinding = exports.HttpContractMapper = exports.BoundHttpRequest = exports.StreamDisconnectedError = exports.StreamProtocolError = exports.StreamErrorControl = exports.registerStreamingCatalog = exports.StreamingSchemaCatalog = exports.getAuthorization = exports.WpAuthorization = exports.AuthorizationDeclaration = exports.AuthorizationType = exports.RouteMetadataFactory = exports.RouteMetadata = exports.IPC_METADATA_KEYS = exports.assertNotInternalApi = exports.assertInternalApi = exports.getIpcMaskSpec = exports.getIpcEndpointKind = exports.getIpcEndpoints = exports.getIpcApiId = exports.isInternalApi = exports.WpIpcEndpoint = exports.WpInternal = exports.assertApiTypeMatchesMcpTools = exports.getApiTypeEndpointNames = exports.getApiTypes = exports.DEFAULT_API_TYPES = exports.API_TYPE_METADATA_KEY = void 0;
13
- exports.NetworkRejectClassifier = exports.NO_REG_CODE = exports.WRONG_COMPANY = exports.WRONG_DOMAIN = exports.EMAIL_NOT_CONFIRMED = exports.NOT_APPROVED = exports.WRONG_LOGIN = exports.WRONG_LOGIN_TYPE = exports.ENTITY_NOT_FOUND = exports.SECRETS = exports.Secrets = exports.getEndpointCaller = exports.isExternalSystemKind = exports.ExternalCaller = exports.DEFAULT_CALLER_KIND = exports.EXTERNAL_SYSTEM_KINDS = exports.getQueueName = exports.assertPubSubConventions = exports.assertApiKind = exports.getApiKind = exports.ENDPOINT_KINDS_BY_API_KIND = exports.Queue = exports.PubSub = exports.Rpc = exports.apiKey = exports.webhook = exports.sharedSecret = exports.oidc = exports.jwt = exports.AuthDeclaration = exports.AuthMeta = exports.GenerateOutputTarget = exports.GenerateOutputLookup = exports.GenerateLayoutProblem = exports.GeneratedApiDocsLayout = exports.McpToolDefinition = exports.McpToolCatalogError = exports.McpToolCatalogFile = exports.ObjectSchemaBuilder = exports.DtoValidationFailure = exports.ApiJsonSchemaValidator = exports.ApiJsonSchemaDiscriminator = exports.ApiJsonSchema = exports.mcpHintsForOperation = exports.getWpMcpTools = exports.getInvalidEndpointsForMcp = exports.WpMcpToolMetadata = exports.WpMcpToolHints = exports.WpMcpTool = exports.InvalidEndpointForMcpMetadata = void 0;
14
- exports.ApiDependencyError = exports.ApiNotFoundError = exports.ApiError = exports.FilterChain = exports.Filter = exports.SerializedError = exports.SerializedMap = exports.RecordSerializer = exports.getDoNotRecordFields = exports.DoNotRecord = exports.RecordedTestCase = exports.RecordedError = exports.RecordedEndpoint = exports.RecorderKeys = exports.ApiMethodInfo = exports.LOG_API_CALL_LOGGER_NAME = exports.ApiCallLogNameImpl = exports.ApiCallLogName = exports.ApiCallInfo = exports.MaskSpec = exports.LogApiCallImpl = exports.ContextMgr = exports.DestinationTrust = exports.WebpiecesCoreHeaders = exports.templateDeriver = exports.WEBPIECES_DEFAULT_ERROR_CLASSIFIER = exports.WebpiecesDefaultErrorClassifier = exports.KeyedErrorClassifier = exports.CallOutcome = exports.ReceivedApiErrorRule = exports.SurfaceEndUserStatus = exports.WEBPIECES_DEFAULT_ERROR_TRANSLATOR = exports.WebpiecesDefaultErrorTranslator = exports.HttpResponseDto = exports.HttpResponseStatus = exports.HttpHeader = exports.RuntimeLocality = exports.ServiceInfo = exports.ApiCallTimeoutError = exports.CallContext = exports.CallDeadline = exports.RetryStrategy = exports.TransportDefault = exports.CallRegistry = exports.ClientRegistry = exports.HeaderRegistry = exports.DateTimeUtil = exports.TimeUtil = exports.DateUtil = exports.InstantUtil = void 0;
15
- exports.McpToolProfilesOptions = exports.Mcp = exports.OAuthAuthorizationErrorRedirect = exports.OAuthErrorResponse = exports.OAuthErrorBody = exports.OAuthBearerChallenge = exports.OAuthErrorExtras = exports.OAuthProtocolError = exports.OAuthText = exports.OAuthErrorStatus = exports.OAuthErrorCode = exports.ApiErrorHttpStatus = exports.RpcCallFailed = exports.ReportableApiFailure = exports.ApiCallSite = exports.ApiErrorBoundary = exports.ApiErrorPayload = exports.ApiErrorCodec = exports.ClientRole = exports.EndUserErrorRegistry = exports.EndUserErrorCode = exports.ApiEndUserBadRequestError = exports.ApiEndUserForbiddenError = exports.ApiEndUserNotFoundError = exports.ApiClientTooOldError = exports.ApiCodedError = exports.ApiNotImplementedError = exports.ApiUnsupportedMediaTypeError = exports.ApiPreconditionFailedError = exports.ApiUnprocessableError = exports.ApiConflictError = exports.ApiEndpointNotFoundError = exports.ApiConnectionError = exports.ApiRetriesExhaustedError = exports.ApiDependencyBackoffError = exports.ApiUnauthorizedError = exports.ApiBadRequestError = exports.ApiEndUserError = exports.ApiRequestTimeoutError = exports.ApiForbiddenError = exports.ApiRateLimitedError = exports.ApiImplementationError = exports.ApiDependencyTimeoutError = exports.ApiUnavailableError = exports.ApiBadGatewayError = void 0;
13
+ exports.NO_REG_CODE = exports.WRONG_COMPANY = exports.WRONG_DOMAIN = exports.EMAIL_NOT_CONFIRMED = exports.NOT_APPROVED = exports.WRONG_LOGIN = exports.WRONG_LOGIN_TYPE = exports.ENTITY_NOT_FOUND = exports.SECRETS = exports.Secrets = exports.getEndpointCaller = exports.isExternalSystemKind = exports.ExternalCaller = exports.DEFAULT_CALLER_KIND = exports.EXTERNAL_SYSTEM_KINDS = exports.getQueueName = exports.assertPubSubConventions = exports.assertApiKind = exports.getApiKind = exports.ENDPOINT_KINDS_BY_API_KIND = exports.Queue = exports.PubSub = exports.Rpc = exports.apiKey = exports.webhook = exports.sharedSecret = exports.oidcSvcs = exports.oidcSameProject = exports.jwt = exports.AuthDeclaration = exports.AuthMeta = exports.GenerateOutputTarget = exports.GenerateOutputLookup = exports.GenerateLayoutProblem = exports.GeneratedApiDocsLayout = exports.McpToolDefinition = exports.McpToolCatalogError = exports.McpToolCatalogFile = exports.ObjectSchemaBuilder = exports.DtoValidationFailure = exports.ApiJsonSchemaValidator = exports.ApiJsonSchemaDiscriminator = exports.ApiJsonSchema = exports.mcpHintsForOperation = exports.getWpMcpTools = exports.getInvalidEndpointsForMcp = exports.WpMcpToolMetadata = exports.WpMcpToolHints = exports.WpMcpTool = exports.InvalidEndpointForMcpMetadata = void 0;
14
+ exports.ApiNotFoundError = exports.ApiError = exports.FilterChain = exports.Filter = exports.SerializedError = exports.SerializedMap = exports.RecordSerializer = exports.getDoNotRecordFields = exports.DoNotRecord = exports.RecordedTestCase = exports.RecordedError = exports.RecordedEndpoint = exports.RecorderKeys = exports.ApiMethodInfo = exports.LOG_API_CALL_LOGGER_NAME = exports.ApiCallLogNameImpl = exports.ApiCallLogName = exports.ApiCallInfo = exports.MaskSpec = exports.LogApiCallImpl = exports.ContextMgr = exports.DestinationTrust = exports.WebpiecesCoreHeaders = exports.templateDeriver = exports.WEBPIECES_DEFAULT_ERROR_CLASSIFIER = exports.WebpiecesDefaultErrorClassifier = exports.KeyedErrorClassifier = exports.CallOutcome = exports.ReceivedApiErrorRule = exports.SurfaceEndUserStatus = exports.WEBPIECES_DEFAULT_ERROR_TRANSLATOR = exports.WebpiecesDefaultErrorTranslator = exports.HttpResponseDto = exports.HttpResponseStatus = exports.HttpHeader = exports.RuntimeLocality = exports.ServiceInfo = exports.ApiCallTimeoutError = exports.CallContext = exports.CallDeadline = exports.RetryStrategy = exports.TransportDefault = exports.CallRegistry = exports.ClientRegistry = exports.HeaderRegistry = exports.DateTimeUtil = exports.TimeUtil = exports.DateUtil = exports.InstantUtil = exports.NetworkRejectClassifier = void 0;
15
+ exports.McpToolProfilesOptions = exports.Mcp = exports.OAuthAuthorizationErrorRedirect = exports.OAuthErrorResponse = exports.OAuthErrorBody = exports.OAuthBearerChallenge = exports.OAuthErrorExtras = exports.OAuthProtocolError = exports.OAuthText = exports.OAuthErrorStatus = exports.OAuthErrorCode = exports.ApiErrorHttpStatus = exports.RpcCallFailed = exports.ReportableApiFailure = exports.ApiCallSite = exports.ApiErrorBoundary = exports.ApiErrorPayload = exports.ApiErrorCodec = exports.ClientRole = exports.EndUserErrorRegistry = exports.EndUserErrorCode = exports.ApiEndUserBadRequestError = exports.ApiEndUserForbiddenError = exports.ApiEndUserNotFoundError = exports.ApiClientTooOldError = exports.ApiCodedError = exports.ApiNotImplementedError = exports.ApiUnsupportedMediaTypeError = exports.ApiPreconditionFailedError = exports.ApiUnprocessableError = exports.ApiConflictError = exports.ApiEndpointNotFoundError = exports.ApiConnectionError = exports.ApiRetriesExhaustedError = exports.ApiDependencyBackoffError = exports.ApiUnauthorizedError = exports.ApiBadRequestError = exports.ApiEndUserError = exports.ApiRequestTimeoutError = exports.ApiForbiddenError = exports.ApiRateLimitedError = exports.ApiImplementationError = exports.ApiDependencyTimeoutError = exports.ApiUnavailableError = exports.ApiBadGatewayError = exports.ApiDependencyError = void 0;
16
16
  var errorUtils_1 = require("./lib/errorUtils");
17
17
  Object.defineProperty(exports, "toError", { enumerable: true, get: function () { return errorUtils_1.toError; } });
18
18
  var ContextKey_1 = require("./ContextKey");
@@ -174,7 +174,8 @@ var auth_mode_1 = require("./http/auth-mode");
174
174
  Object.defineProperty(exports, "AuthMeta", { enumerable: true, get: function () { return auth_mode_1.AuthMeta; } });
175
175
  Object.defineProperty(exports, "AuthDeclaration", { enumerable: true, get: function () { return auth_mode_1.AuthDeclaration; } });
176
176
  Object.defineProperty(exports, "jwt", { enumerable: true, get: function () { return auth_mode_1.jwt; } });
177
- Object.defineProperty(exports, "oidc", { enumerable: true, get: function () { return auth_mode_1.oidc; } });
177
+ Object.defineProperty(exports, "oidcSameProject", { enumerable: true, get: function () { return auth_mode_1.oidcSameProject; } });
178
+ Object.defineProperty(exports, "oidcSvcs", { enumerable: true, get: function () { return auth_mode_1.oidcSvcs; } });
178
179
  Object.defineProperty(exports, "sharedSecret", { enumerable: true, get: function () { return auth_mode_1.sharedSecret; } });
179
180
  Object.defineProperty(exports, "webhook", { enumerable: true, get: function () { return auth_mode_1.webhook; } });
180
181
  Object.defineProperty(exports, "apiKey", { enumerable: true, get: function () { return auth_mode_1.apiKey; } });