@blamejs/core 0.7.106 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/CHANGELOG.md +19 -1
  2. package/NOTICE +17 -1
  3. package/README.md +4 -3
  4. package/index.js +16 -0
  5. package/lib/asyncapi-bindings.js +160 -0
  6. package/lib/asyncapi-traits.js +143 -0
  7. package/lib/asyncapi.js +531 -0
  8. package/lib/audit.js +6 -0
  9. package/lib/auth/acr-vocabulary.js +265 -0
  10. package/lib/auth/auth-time-tracker.js +111 -0
  11. package/lib/auth/elevation-grant.js +306 -0
  12. package/lib/auth/sd-jwt-vc-disclosure.js +95 -0
  13. package/lib/auth/sd-jwt-vc-holder.js +203 -0
  14. package/lib/auth/sd-jwt-vc-issuer.js +197 -0
  15. package/lib/auth/sd-jwt-vc.js +526 -0
  16. package/lib/auth/step-up-policy.js +335 -0
  17. package/lib/auth/step-up.js +445 -0
  18. package/lib/compliance-ai-act-logging.js +186 -0
  19. package/lib/compliance-ai-act-prohibited.js +205 -0
  20. package/lib/compliance-ai-act-risk.js +189 -0
  21. package/lib/compliance-ai-act-transparency.js +200 -0
  22. package/lib/compliance-ai-act.js +558 -0
  23. package/lib/compliance.js +2 -0
  24. package/lib/crypto.js +32 -0
  25. package/lib/flag-cache.js +136 -0
  26. package/lib/flag-evaluation-context.js +135 -0
  27. package/lib/flag-providers.js +279 -0
  28. package/lib/flag-targeting.js +210 -0
  29. package/lib/flag.js +284 -0
  30. package/lib/inbox.js +367 -0
  31. package/lib/mail-arc-sign.js +372 -0
  32. package/lib/mail-auth.js +2 -0
  33. package/lib/middleware/ai-act-disclosure.js +166 -0
  34. package/lib/middleware/asyncapi-serve.js +136 -0
  35. package/lib/middleware/flag-context.js +76 -0
  36. package/lib/middleware/index.js +15 -0
  37. package/lib/middleware/openapi-serve.js +143 -0
  38. package/lib/middleware/require-step-up.js +186 -0
  39. package/lib/openapi-paths-builder.js +248 -0
  40. package/lib/openapi-schema-walk.js +192 -0
  41. package/lib/openapi-security.js +169 -0
  42. package/lib/openapi-yaml.js +154 -0
  43. package/lib/openapi.js +443 -0
  44. package/lib/pqc-software.js +195 -0
  45. package/lib/vault/index.js +3 -0
  46. package/lib/vault-aad.js +259 -0
  47. package/lib/vendor/MANIFEST.json +29 -0
  48. package/lib/vendor/noble-post-quantum.cjs +18 -0
  49. package/lib/ws-client.js +829 -0
  50. package/package.json +1 -1
  51. package/sbom.cyclonedx.json +6 -6
@@ -0,0 +1,248 @@
1
+ "use strict";
2
+ /**
3
+ * OpenAPI 3.1 — paths / operations builder.
4
+ *
5
+ * Internal to lib/openapi.js. Holds the per-path operation table
6
+ * (method to operationObject) and produces the final `paths` map used
7
+ * by the document builder.
8
+ *
9
+ * Path keys MUST start with `/` per OpenAPI 3.1 §4.8. Path templates
10
+ * use `{name}` placeholders that bind to declared `parameters` of
11
+ * `in: path`. The builder validates that every `{name}` placeholder
12
+ * has a matching declared parameter at build-time.
13
+ *
14
+ * Operation methods accepted: get / put / post / delete / options /
15
+ * head / patch / trace (RFC 9110 + OpenAPI 3.1 §4.8.5).
16
+ */
17
+
18
+ var validateOpts = require("./validate-opts");
19
+ var schemaWalk = require("./openapi-schema-walk");
20
+ var { defineClass } = require("./framework-error");
21
+ var OpenApiError = defineClass("OpenApiError", { alwaysPermanent: true });
22
+
23
+ var VALID_METHODS = ["get", "put", "post", "delete",
24
+ "options", "head", "patch", "trace"];
25
+
26
+ // Path-template parameter extraction — each `{name}` is a path param.
27
+ function _extractPathParams(pathTemplate) {
28
+ var out = [];
29
+ var pattern = /\{([a-zA-Z_][a-zA-Z0-9_-]*)\}/g;
30
+ var matched = pattern.exec(pathTemplate);
31
+ while (matched !== null) {
32
+ out.push(matched[1]);
33
+ matched = pattern.exec(pathTemplate);
34
+ }
35
+ return out;
36
+ }
37
+
38
+ function PathsBuilder() {
39
+ this._paths = {};
40
+ }
41
+
42
+ PathsBuilder.prototype.add = function (method, urlPattern, opts) {
43
+ opts = opts || {};
44
+ if (typeof method !== "string" || VALID_METHODS.indexOf(method.toLowerCase()) === -1) {
45
+ throw new OpenApiError("openapi/bad-method",
46
+ "paths.add: method must be one of " + VALID_METHODS.join(", ") +
47
+ " - got " + JSON.stringify(method));
48
+ }
49
+ validateOpts.requireNonEmptyString(urlPattern, "paths.add: urlPattern",
50
+ OpenApiError, "openapi/bad-path");
51
+ if (urlPattern.charAt(0) !== "/") {
52
+ throw new OpenApiError("openapi/bad-path",
53
+ "paths.add: urlPattern must start with '/' - got " +
54
+ JSON.stringify(urlPattern));
55
+ }
56
+ validateOpts(opts, [
57
+ "summary", "description", "operationId", "tags",
58
+ "parameters", "requestBody", "responses",
59
+ "security", "deprecated", "servers", "externalDocs",
60
+ ], "paths.add");
61
+
62
+ var op = {};
63
+ if (typeof opts.summary === "string") op.summary = opts.summary;
64
+ if (typeof opts.description === "string") op.description = opts.description;
65
+ if (typeof opts.operationId === "string") op.operationId = opts.operationId;
66
+ if (Array.isArray(opts.tags) && opts.tags.length > 0) {
67
+ op.tags = opts.tags.map(function (t) {
68
+ if (typeof t !== "string" || t.length === 0) {
69
+ throw new OpenApiError("openapi/bad-tag",
70
+ "paths.add: tags must be non-empty strings");
71
+ }
72
+ return t;
73
+ });
74
+ }
75
+
76
+ // Parameters
77
+ var declaredPathParams = Object.create(null);
78
+ if (Array.isArray(opts.parameters)) {
79
+ op.parameters = [];
80
+ for (var i = 0; i < opts.parameters.length; i += 1) {
81
+ var p = _normaliseParameter(opts.parameters[i], "paths.add: parameters[" + i + "]");
82
+ op.parameters.push(p);
83
+ if (p.in === "path") declaredPathParams[p.name] = true;
84
+ }
85
+ }
86
+ // Verify every {placeholder} in path is declared.
87
+ var placeholders = _extractPathParams(urlPattern);
88
+ for (var j = 0; j < placeholders.length; j += 1) {
89
+ if (!declaredPathParams[placeholders[j]]) {
90
+ throw new OpenApiError("openapi/missing-path-param",
91
+ "paths.add: path template " + JSON.stringify(urlPattern) +
92
+ " references {" + placeholders[j] +
93
+ "} but no parameter with in=path name=" + JSON.stringify(placeholders[j]) +
94
+ " was declared");
95
+ }
96
+ }
97
+
98
+ // Request body
99
+ if (opts.requestBody) {
100
+ op.requestBody = _normaliseRequestBody(opts.requestBody, "paths.add: requestBody");
101
+ }
102
+
103
+ // Responses (required)
104
+ if (!opts.responses || typeof opts.responses !== "object") {
105
+ throw new OpenApiError("openapi/missing-responses",
106
+ "paths.add: responses object is required (per OpenAPI 3.1 §4.8.5)");
107
+ }
108
+ op.responses = _normaliseResponses(opts.responses, "paths.add: responses");
109
+
110
+ if (Array.isArray(opts.security)) op.security = opts.security.slice();
111
+ if (opts.deprecated === true) op.deprecated = true;
112
+ if (Array.isArray(opts.servers)) op.servers = opts.servers.slice();
113
+ if (opts.externalDocs) op.externalDocs = opts.externalDocs;
114
+
115
+ if (!this._paths[urlPattern]) this._paths[urlPattern] = {};
116
+ if (this._paths[urlPattern][method.toLowerCase()]) {
117
+ throw new OpenApiError("openapi/duplicate-operation",
118
+ "paths.add: duplicate operation " + method.toUpperCase() + " " + urlPattern);
119
+ }
120
+ this._paths[urlPattern][method.toLowerCase()] = op;
121
+ return op;
122
+ };
123
+
124
+ function _normaliseParameter(input, label) {
125
+ if (!input || typeof input !== "object") {
126
+ throw new OpenApiError("openapi/bad-parameter",
127
+ label + ": parameter must be an object");
128
+ }
129
+ validateOpts.requireNonEmptyString(input.name, label + ": name",
130
+ OpenApiError, "openapi/bad-parameter");
131
+ var validIn = ["path", "query", "header", "cookie"];
132
+ if (validIn.indexOf(input.in) === -1) {
133
+ throw new OpenApiError("openapi/bad-parameter",
134
+ label + ": in must be one of " + validIn.join(", ") +
135
+ " - got " + JSON.stringify(input.in));
136
+ }
137
+ if (input.in === "path" && input.required !== true) {
138
+ throw new OpenApiError("openapi/bad-parameter",
139
+ label + ": path parameter " + JSON.stringify(input.name) +
140
+ " must have required=true (per OpenAPI 3.1 §4.8.10)");
141
+ }
142
+ var p = {
143
+ name: input.name,
144
+ in: input.in,
145
+ };
146
+ if (typeof input.description === "string") p.description = input.description;
147
+ if (input.required === true) p.required = true;
148
+ if (input.deprecated === true) p.deprecated = true;
149
+ if (input.allowEmptyValue === true) p.allowEmptyValue = true;
150
+ if (input.schema != null) {
151
+ p.schema = schemaWalk.walk(input.schema);
152
+ }
153
+ if (input.example != null) p.example = input.example;
154
+ return p;
155
+ }
156
+
157
+ function _normaliseRequestBody(input, label) {
158
+ if (!input || typeof input !== "object") {
159
+ throw new OpenApiError("openapi/bad-request-body",
160
+ label + ": requestBody must be an object");
161
+ }
162
+ if (!input.content || typeof input.content !== "object") {
163
+ throw new OpenApiError("openapi/bad-request-body",
164
+ label + ": content map required (e.g. { 'application/json': { schema: ... } })");
165
+ }
166
+ var out = { content: {} };
167
+ if (typeof input.description === "string") out.description = input.description;
168
+ if (input.required === true) out.required = true;
169
+ for (var ct in input.content) {
170
+ if (!Object.prototype.hasOwnProperty.call(input.content, ct)) continue;
171
+ var entry = input.content[ct];
172
+ if (!entry || typeof entry !== "object") {
173
+ throw new OpenApiError("openapi/bad-request-body",
174
+ label + ": content[" + JSON.stringify(ct) + "] must be an object");
175
+ }
176
+ var ce = {};
177
+ if (entry.schema != null) ce.schema = schemaWalk.walk(entry.schema);
178
+ if (entry.example != null) ce.example = entry.example;
179
+ if (entry.examples != null) ce.examples = entry.examples;
180
+ if (entry.encoding != null) ce.encoding = entry.encoding;
181
+ out.content[ct] = ce;
182
+ }
183
+ return out;
184
+ }
185
+
186
+ function _normaliseResponses(input, label) {
187
+ var out = {};
188
+ var statusKeys = Object.keys(input);
189
+ if (statusKeys.length === 0) {
190
+ throw new OpenApiError("openapi/missing-responses",
191
+ label + ": at least one response required");
192
+ }
193
+ for (var i = 0; i < statusKeys.length; i += 1) {
194
+ var status = statusKeys[i];
195
+ var resp = input[status];
196
+ if (!resp || typeof resp !== "object") {
197
+ throw new OpenApiError("openapi/bad-response",
198
+ label + "[" + status + "]: response must be an object");
199
+ }
200
+ var r = {};
201
+ if (typeof resp.description === "string") {
202
+ r.description = resp.description;
203
+ } else {
204
+ throw new OpenApiError("openapi/missing-response-description",
205
+ label + "[" + status + "]: description is required (per OpenAPI 3.1 §4.8.16)");
206
+ }
207
+ if (resp.headers != null) r.headers = resp.headers;
208
+ if (resp.content != null) {
209
+ r.content = {};
210
+ for (var ct in resp.content) {
211
+ if (!Object.prototype.hasOwnProperty.call(resp.content, ct)) continue;
212
+ var entry = resp.content[ct];
213
+ if (!entry || typeof entry !== "object") continue;
214
+ var ce = {};
215
+ if (entry.schema != null) ce.schema = schemaWalk.walk(entry.schema);
216
+ if (entry.example != null) ce.example = entry.example;
217
+ if (entry.examples != null) ce.examples = entry.examples;
218
+ r.content[ct] = ce;
219
+ }
220
+ }
221
+ if (resp.links != null) r.links = resp.links;
222
+ out[status] = r;
223
+ }
224
+ return out;
225
+ }
226
+
227
+ PathsBuilder.prototype.toMap = function () {
228
+ var sorted = Object.keys(this._paths).sort();
229
+ var out = {};
230
+ for (var i = 0; i < sorted.length; i += 1) {
231
+ var pathKey = sorted[i];
232
+ var pathItem = this._paths[pathKey];
233
+ var ordered = {};
234
+ for (var j = 0; j < VALID_METHODS.length; j += 1) {
235
+ var method = VALID_METHODS[j];
236
+ if (pathItem[method]) ordered[method] = pathItem[method];
237
+ }
238
+ out[pathKey] = ordered;
239
+ }
240
+ return out;
241
+ };
242
+
243
+ module.exports = {
244
+ PathsBuilder: PathsBuilder,
245
+ VALID_METHODS: VALID_METHODS,
246
+ _extractPathParams: _extractPathParams,
247
+ OpenApiError: OpenApiError,
248
+ };
@@ -0,0 +1,192 @@
1
+ "use strict";
2
+ /**
3
+ * OpenAPI 3.1 — converts a b.safeSchema description into the JSON
4
+ * Schema dialect that OpenAPI 3.1 uses (which IS JSON Schema 2020-12
5
+ * proper, not the OpenAPI 3.0 fork). Operators pass either:
6
+ *
7
+ * - A b.safeSchema object (with the framework's `.parse / .optional /
8
+ * ...` interface) — we walk the spec to produce JSON Schema.
9
+ *
10
+ * - A plain JSON Schema object — passes through unchanged (just
11
+ * validated for shape so a typo in the operator's hand-written
12
+ * schema fails at build-time, not at consumer-time).
13
+ *
14
+ * - A primitive type name like "string" / "integer" / "boolean" —
15
+ * translated to the corresponding JSON Schema scalar.
16
+ */
17
+
18
+ var validateOpts = require("./validate-opts");
19
+ var { defineClass } = require("./framework-error");
20
+ var OpenApiError = defineClass("OpenApiError", { alwaysPermanent: true });
21
+
22
+ var TYPE_KEYWORDS = ["type", "properties", "items", "enum", "const",
23
+ "format", "pattern", "anyOf", "oneOf", "allOf",
24
+ "not", "$ref", "$id"];
25
+
26
+ function _isPlainObject(v) {
27
+ return !!v && typeof v === "object" && !Array.isArray(v);
28
+ }
29
+
30
+ function _isJsonSchemaShape(v) {
31
+ if (!_isPlainObject(v)) return false;
32
+ for (var i = 0; i < TYPE_KEYWORDS.length; i += 1) {
33
+ if (Object.prototype.hasOwnProperty.call(v, TYPE_KEYWORDS[i])) return true;
34
+ }
35
+ return false;
36
+ }
37
+
38
+ function _isSafeSchema(v) {
39
+ return !!v && typeof v === "object" &&
40
+ typeof v.parse === "function" && typeof v._kind === "string";
41
+ }
42
+
43
+ function _safeSchemaToJsonSchema(schema) {
44
+ var out = {};
45
+ switch (schema._kind) {
46
+ case "string":
47
+ out.type = "string";
48
+ if (typeof schema._minLength === "number") out.minLength = schema._minLength;
49
+ if (typeof schema._maxLength === "number") out.maxLength = schema._maxLength;
50
+ if (schema._format) out.format = schema._format;
51
+ if (schema._regex && schema._regex.source) out.pattern = schema._regex.source;
52
+ break;
53
+ case "number":
54
+ case "integer":
55
+ out.type = (schema._kind === "integer") ? "integer" : "number";
56
+ if (typeof schema._min === "number") out.minimum = schema._min;
57
+ if (typeof schema._max === "number") out.maximum = schema._max;
58
+ if (schema._isInt === true) out.type = "integer";
59
+ break;
60
+ case "boolean":
61
+ out.type = "boolean";
62
+ break;
63
+ case "literal":
64
+ out.const = schema._value;
65
+ break;
66
+ case "enum":
67
+ out.enum = (schema._values || []).slice();
68
+ break;
69
+ case "null":
70
+ out.type = "null";
71
+ break;
72
+ case "array":
73
+ out.type = "array";
74
+ if (schema._element != null) out.items = walk(schema._element);
75
+ if (typeof schema._minItems === "number") out.minItems = schema._minItems;
76
+ if (typeof schema._maxItems === "number") out.maxItems = schema._maxItems;
77
+ break;
78
+ case "object":
79
+ out.type = "object";
80
+ out.properties = {};
81
+ var requiredList = [];
82
+ var shape = schema.shape || schema._shape || {};
83
+ for (var key in shape) {
84
+ if (Object.prototype.hasOwnProperty.call(shape, key)) {
85
+ var childSchema = shape[key];
86
+ out.properties[key] = walk(childSchema);
87
+ if (!childSchema._isOptional) {
88
+ requiredList.push(key);
89
+ }
90
+ }
91
+ }
92
+ if (requiredList.length > 0) out.required = requiredList;
93
+ out.additionalProperties = (schema._mode === "passthrough") ? true : false;
94
+ break;
95
+ case "record":
96
+ out.type = "object";
97
+ if (schema._valueSchema) out.additionalProperties = walk(schema._valueSchema);
98
+ break;
99
+ case "union":
100
+ out.oneOf = (schema._options || []).map(walk);
101
+ break;
102
+ case "any":
103
+ case "unknown":
104
+ break;
105
+ default:
106
+ break;
107
+ }
108
+ if (schema._description) out.description = schema._description;
109
+ if (schema._example != null) out.example = schema._example;
110
+ if (schema._isNullable === true && typeof out.type === "string") {
111
+ out.type = [out.type, "null"];
112
+ }
113
+ return out;
114
+ }
115
+
116
+ function walk(input) {
117
+ if (input == null) return {};
118
+ if (typeof input === "string") {
119
+ return { type: input };
120
+ }
121
+ if (_isSafeSchema(input)) {
122
+ return _safeSchemaToJsonSchema(input);
123
+ }
124
+ if (_isJsonSchemaShape(input)) {
125
+ return _cloneJsonSchema(input);
126
+ }
127
+ if (_isPlainObject(input)) {
128
+ // Hand-shaped object — operator passed a JSON-Schema-like object
129
+ // without a recognised keyword; clone as-is and let the spec
130
+ // validation in build() flag it.
131
+ return _cloneJsonSchema(input);
132
+ }
133
+ throw new OpenApiError("openapi/bad-schema",
134
+ "schema-walk: unsupported schema input — got " + typeof input);
135
+ }
136
+
137
+ function _cloneJsonSchema(obj) {
138
+ if (obj == null || typeof obj !== "object") return obj;
139
+ if (Array.isArray(obj)) {
140
+ var arrOut = [];
141
+ for (var i = 0; i < obj.length; i += 1) {
142
+ arrOut.push(_cloneJsonSchema(obj[i]));
143
+ }
144
+ return arrOut;
145
+ }
146
+ var out = {};
147
+ for (var key in obj) {
148
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
149
+ out[key] = _cloneJsonSchema(obj[key]);
150
+ }
151
+ }
152
+ return out;
153
+ }
154
+
155
+ // Validates a JSON Schema document for the most common authoring
156
+ // errors. Used at build-time so a typo doesn't reach the spec
157
+ // consumer. Not a full JSON-Schema-vocabulary validator — that's
158
+ // outside scope; operators with strict needs run a downstream
159
+ // validator like ajv against the emitted document.
160
+ function validateJsonSchema(schema, label) {
161
+ validateOpts.requireNonEmptyString(label || "schema", "validateJsonSchema: label",
162
+ OpenApiError, "openapi/bad-schema");
163
+ if (!_isPlainObject(schema)) {
164
+ throw new OpenApiError("openapi/bad-schema",
165
+ label + ": schema must be a plain object");
166
+ }
167
+ if (typeof schema.type === "string") {
168
+ var validTypes = ["string", "number", "integer", "boolean",
169
+ "object", "array", "null"];
170
+ if (validTypes.indexOf(schema.type) === -1) {
171
+ throw new OpenApiError("openapi/bad-schema",
172
+ label + ": invalid type " + JSON.stringify(schema.type));
173
+ }
174
+ }
175
+ if (Array.isArray(schema.type)) {
176
+ for (var i = 0; i < schema.type.length; i += 1) {
177
+ if (typeof schema.type[i] !== "string") {
178
+ throw new OpenApiError("openapi/bad-schema",
179
+ label + ": type[" + i + "] must be a string");
180
+ }
181
+ }
182
+ }
183
+ return true;
184
+ }
185
+
186
+ module.exports = {
187
+ walk: walk,
188
+ validateJsonSchema: validateJsonSchema,
189
+ _isSafeSchema: _isSafeSchema,
190
+ _isJsonSchemaShape: _isJsonSchemaShape,
191
+ OpenApiError: OpenApiError,
192
+ };
@@ -0,0 +1,169 @@
1
+ "use strict";
2
+ /**
3
+ * OpenAPI 3.1 — security-scheme builders.
4
+ *
5
+ * Each helper returns a JSON-Schema-compatible securityScheme object
6
+ * the OpenAPI builder slots under `components.securitySchemes`.
7
+ * Operators reference them by name in `security` requirements:
8
+ *
9
+ * var openapi = b.openapi.create({ ... });
10
+ * openapi.security.add("bearerJwt", b.openapi.security.bearer({ jwtBearer: true }));
11
+ * openapi.path("get", "/me", { security: [{ bearerJwt: [] }] });
12
+ *
13
+ * Helpers cover every IANA-registered scheme operators reach for:
14
+ *
15
+ * .bearer({ jwtBearer? }) → Bearer token
16
+ * .basic() → HTTP Basic auth
17
+ * .apiKey({ name, in }) → API key in header / query / cookie
18
+ * .oauth2({ flows }) → OAuth2 with AuthCode / ClientCreds /
19
+ * Implicit / Password flow specs
20
+ * .openIdConnect({ url }) → OIDC discovery URL
21
+ * .mtls() → mutual TLS (RFC 8705)
22
+ * .dpop() → DPoP-bound bearer (RFC 9449)
23
+ *
24
+ * The helpers throw at config-time on bad opts (config-time-throw discipline) so
25
+ * an operator's typo in the OpenAPI document fails at the build step,
26
+ * not at consumer-validation time.
27
+ */
28
+
29
+ var validateOpts = require("./validate-opts");
30
+ var { defineClass } = require("./framework-error");
31
+ var OpenApiError = defineClass("OpenApiError", { alwaysPermanent: true });
32
+
33
+ function bearer(opts) {
34
+ opts = opts || {};
35
+ validateOpts(opts, ["jwtBearer", "description"], "openapi.security.bearer");
36
+ var out = {
37
+ type: "http",
38
+ scheme: "bearer",
39
+ };
40
+ if (opts.jwtBearer === true) out.bearerFormat = "JWT";
41
+ if (typeof opts.description === "string" && opts.description.length > 0) {
42
+ out.description = opts.description;
43
+ }
44
+ return out;
45
+ }
46
+
47
+ function basic(opts) {
48
+ opts = opts || {};
49
+ validateOpts(opts, ["description"], "openapi.security.basic");
50
+ var out = { type: "http", scheme: "basic" };
51
+ if (typeof opts.description === "string" && opts.description.length > 0) {
52
+ out.description = opts.description;
53
+ }
54
+ return out;
55
+ }
56
+
57
+ function apiKey(opts) {
58
+ opts = opts || {};
59
+ validateOpts(opts, ["name", "in", "description"], "openapi.security.apiKey");
60
+ validateOpts.requireNonEmptyString(opts.name, "apiKey: name",
61
+ OpenApiError, "openapi/bad-security");
62
+ var validIn = ["header", "query", "cookie"];
63
+ if (validIn.indexOf(opts.in) === -1) {
64
+ throw new OpenApiError("openapi/bad-security",
65
+ "apiKey: in must be one of " + validIn.join(", ") +
66
+ " — got " + JSON.stringify(opts.in));
67
+ }
68
+ var out = { type: "apiKey", name: opts.name, in: opts.in };
69
+ if (typeof opts.description === "string" && opts.description.length > 0) {
70
+ out.description = opts.description;
71
+ }
72
+ return out;
73
+ }
74
+
75
+ function _validateFlow(name, flow) {
76
+ if (!flow || typeof flow !== "object") {
77
+ throw new OpenApiError("openapi/bad-security",
78
+ "oauth2." + name + ": flow must be an object");
79
+ }
80
+ if (typeof flow.scopes !== "object" || flow.scopes == null) {
81
+ throw new OpenApiError("openapi/bad-security",
82
+ "oauth2." + name + ": scopes must be an object (scopeName -> description)");
83
+ }
84
+ if (name === "authorizationCode" || name === "implicit") {
85
+ validateOpts.requireNonEmptyString(flow.authorizationUrl,
86
+ "oauth2." + name + ": authorizationUrl",
87
+ OpenApiError, "openapi/bad-security");
88
+ }
89
+ if (name === "authorizationCode" || name === "password" || name === "clientCredentials") {
90
+ validateOpts.requireNonEmptyString(flow.tokenUrl,
91
+ "oauth2." + name + ": tokenUrl",
92
+ OpenApiError, "openapi/bad-security");
93
+ }
94
+ }
95
+
96
+ function oauth2(opts) {
97
+ opts = opts || {};
98
+ validateOpts(opts, ["flows", "description"], "openapi.security.oauth2");
99
+ if (!opts.flows || typeof opts.flows !== "object") {
100
+ throw new OpenApiError("openapi/bad-security",
101
+ "oauth2: flows must be an object — at least one of authorizationCode / clientCredentials / implicit / password");
102
+ }
103
+ var validFlowNames = ["authorizationCode", "clientCredentials", "implicit", "password"];
104
+ for (var k in opts.flows) {
105
+ if (!Object.prototype.hasOwnProperty.call(opts.flows, k)) continue;
106
+ if (validFlowNames.indexOf(k) === -1) {
107
+ throw new OpenApiError("openapi/bad-security",
108
+ "oauth2: unknown flow " + JSON.stringify(k) +
109
+ " — valid: " + validFlowNames.join(", "));
110
+ }
111
+ _validateFlow(k, opts.flows[k]);
112
+ }
113
+ var out = { type: "oauth2", flows: opts.flows };
114
+ if (typeof opts.description === "string" && opts.description.length > 0) {
115
+ out.description = opts.description;
116
+ }
117
+ return out;
118
+ }
119
+
120
+ function openIdConnect(opts) {
121
+ opts = opts || {};
122
+ validateOpts(opts, ["url", "description"], "openapi.security.openIdConnect");
123
+ validateOpts.requireNonEmptyString(opts.url,
124
+ "openIdConnect: url", OpenApiError, "openapi/bad-security");
125
+ var out = { type: "openIdConnect", openIdConnectUrl: opts.url };
126
+ if (typeof opts.description === "string" && opts.description.length > 0) {
127
+ out.description = opts.description;
128
+ }
129
+ return out;
130
+ }
131
+
132
+ // mTLS (RFC 8705) — modeled in OpenAPI 3.1 as `mutualTLS` security
133
+ // scheme type added in the 3.1 spec.
134
+ function mtls(opts) {
135
+ opts = opts || {};
136
+ validateOpts(opts, ["description"], "openapi.security.mtls");
137
+ var out = { type: "mutualTLS" };
138
+ if (typeof opts.description === "string" && opts.description.length > 0) {
139
+ out.description = opts.description;
140
+ }
141
+ return out;
142
+ }
143
+
144
+ // DPoP-bound bearer — emitted as a Bearer scheme with a description
145
+ // noting the DPoP requirement; OpenAPI doesn't define a first-class
146
+ // DPoP scheme yet.
147
+ function dpop(opts) {
148
+ opts = opts || {};
149
+ validateOpts(opts, ["description"], "openapi.security.dpop");
150
+ var desc = (typeof opts.description === "string" && opts.description.length > 0)
151
+ ? opts.description
152
+ : "Bearer token bound to a DPoP proof per RFC 9449. Client MUST send the access token in `Authorization: DPoP <token>` and the DPoP proof in the `DPoP` header.";
153
+ return {
154
+ type: "http",
155
+ scheme: "dpop",
156
+ description: desc,
157
+ };
158
+ }
159
+
160
+ module.exports = {
161
+ bearer: bearer,
162
+ basic: basic,
163
+ apiKey: apiKey,
164
+ oauth2: oauth2,
165
+ openIdConnect: openIdConnect,
166
+ mtls: mtls,
167
+ dpop: dpop,
168
+ OpenApiError: OpenApiError,
169
+ };