securenow 7.8.1 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NPM_README.md +14 -19
- package/README.md +11 -11
- package/SKILL-API.md +15 -15
- package/SKILL-CLI.md +13 -12
- package/app-config.js +12 -145
- package/cli/apiKey.js +15 -6
- package/cli/auth.js +4 -4
- package/cli/config.js +3 -10
- package/cli/credentials.js +2 -2
- package/cli/diagnostics.js +2 -2
- package/cli/human.js +13 -8
- package/cli/run.js +1 -5
- package/cli/utils.js +2 -3
- package/cli.js +13 -15
- package/console-instrumentation.js +1 -1
- package/firewall-only.js +4 -7
- package/mcp/catalog.js +540 -16
- package/mcp/server.js +1 -1
- package/nextjs-auto-capture.js +3 -6
- package/nextjs-middleware.js +2 -4
- package/nextjs-wrapper.js +3 -6
- package/nextjs.js +0 -10
- package/package.json +2 -3
- package/rate-limits.js +0 -2
- package/register-vite.js +5 -12
- package/register.js +5 -13
- package/resolve-ip.js +1 -1
- package/tracing.d.ts +1 -1
- package/tracing.js +2 -2
- package/web-vite.mjs +58 -62
package/mcp/server.js
CHANGED
|
@@ -95,7 +95,7 @@ function localAuthStatus() {
|
|
|
95
95
|
const apiKey = config.getApiKey();
|
|
96
96
|
const hasBearer = !!(token || apiKey);
|
|
97
97
|
const runtimeFirewallWarning = app && !apiKey
|
|
98
|
-
? 'Runtime app is connected, but the
|
|
98
|
+
? 'Runtime app is connected, but the runtime API key is missing. Run `npx securenow app connect` or `npx securenow api-key set snk_live_...` to refresh .securenow/runtime.json.'
|
|
99
99
|
: null;
|
|
100
100
|
return {
|
|
101
101
|
authenticated: hasBearer,
|
package/nextjs-auto-capture.js
CHANGED
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
|
|
19
19
|
const { trace } = require('@opentelemetry/api');
|
|
20
20
|
const appConfig = require('./app-config');
|
|
21
|
-
const env = appConfig.env;
|
|
22
21
|
|
|
23
22
|
// Default sensitive fields to redact
|
|
24
23
|
const DEFAULT_SENSITIVE_FIELDS = [
|
|
@@ -56,8 +55,8 @@ async function safeBodyCapture(request, span) {
|
|
|
56
55
|
|
|
57
56
|
try {
|
|
58
57
|
const contentType = request.headers.get('content-type') || '';
|
|
59
|
-
const maxBodySize =
|
|
60
|
-
const customSensitiveFields = (
|
|
58
|
+
const maxBodySize = appConfig.numberConfig('capture.maxBodySize', 10240, 1024);
|
|
59
|
+
const customSensitiveFields = appConfig.listConfig('capture.sensitiveFields');
|
|
61
60
|
const allSensitiveFields = [...DEFAULT_SENSITIVE_FIELDS, ...customSensitiveFields];
|
|
62
61
|
|
|
63
62
|
// Only for supported types
|
|
@@ -127,8 +126,7 @@ async function safeBodyCapture(request, span) {
|
|
|
127
126
|
* Check if body capture is enabled
|
|
128
127
|
*/
|
|
129
128
|
function isBodyCaptureEnabled() {
|
|
130
|
-
|
|
131
|
-
return !/^(0|false)$/i.test(String(env('SECURENOW_CAPTURE_BODY') ?? ''));
|
|
129
|
+
return appConfig.boolConfig('capture.body', true);
|
|
132
130
|
}
|
|
133
131
|
|
|
134
132
|
/**
|
|
@@ -195,4 +193,3 @@ module.exports = {
|
|
|
195
193
|
isBodyCaptureEnabled,
|
|
196
194
|
};
|
|
197
195
|
|
|
198
|
-
|
package/nextjs-middleware.js
CHANGED
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
|
|
18
18
|
const { trace, context, SpanStatusCode } = require('@opentelemetry/api');
|
|
19
19
|
const appConfig = require('./app-config');
|
|
20
|
-
const env = appConfig.env;
|
|
21
20
|
|
|
22
21
|
// Default sensitive fields to redact
|
|
23
22
|
const DEFAULT_SENSITIVE_FIELDS = [
|
|
@@ -101,8 +100,8 @@ async function middleware(request) {
|
|
|
101
100
|
|
|
102
101
|
try {
|
|
103
102
|
const contentType = request.headers.get('content-type') || '';
|
|
104
|
-
const maxBodySize =
|
|
105
|
-
const customSensitiveFields = (
|
|
103
|
+
const maxBodySize = appConfig.numberConfig('capture.maxBodySize', 10240, 1024);
|
|
104
|
+
const customSensitiveFields = appConfig.listConfig('capture.sensitiveFields');
|
|
106
105
|
const allSensitiveFields = [...DEFAULT_SENSITIVE_FIELDS, ...customSensitiveFields];
|
|
107
106
|
|
|
108
107
|
// Only capture supported types
|
|
@@ -184,4 +183,3 @@ module.exports = {
|
|
|
184
183
|
};
|
|
185
184
|
|
|
186
185
|
|
|
187
|
-
|
package/nextjs-wrapper.js
CHANGED
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
|
|
18
18
|
const { trace } = require('@opentelemetry/api');
|
|
19
19
|
const appConfig = require('./app-config');
|
|
20
|
-
const env = appConfig.env;
|
|
21
20
|
|
|
22
21
|
// Default sensitive fields to redact
|
|
23
22
|
const DEFAULT_SENSITIVE_FIELDS = [
|
|
@@ -51,8 +50,7 @@ function redactSensitiveData(obj, sensitiveFields = DEFAULT_SENSITIVE_FIELDS) {
|
|
|
51
50
|
* Capture body from Request object (clone to avoid consuming)
|
|
52
51
|
*/
|
|
53
52
|
async function captureRequestBody(request) {
|
|
54
|
-
|
|
55
|
-
const captureBody = !/^(0|false)$/i.test(String(env('SECURENOW_CAPTURE_BODY') ?? ''));
|
|
53
|
+
const captureBody = appConfig.boolConfig('capture.body', true);
|
|
56
54
|
|
|
57
55
|
if (!captureBody) return;
|
|
58
56
|
if (!['POST', 'PUT', 'PATCH'].includes(request.method)) return;
|
|
@@ -62,8 +60,8 @@ async function captureRequestBody(request) {
|
|
|
62
60
|
|
|
63
61
|
try {
|
|
64
62
|
const contentType = request.headers.get('content-type') || '';
|
|
65
|
-
const maxBodySize =
|
|
66
|
-
const customSensitiveFields = (
|
|
63
|
+
const maxBodySize = appConfig.numberConfig('capture.maxBodySize', 10240, 1024);
|
|
64
|
+
const customSensitiveFields = appConfig.listConfig('capture.sensitiveFields');
|
|
67
65
|
const allSensitiveFields = [...DEFAULT_SENSITIVE_FIELDS, ...customSensitiveFields];
|
|
68
66
|
|
|
69
67
|
// Only for supported types
|
|
@@ -155,4 +153,3 @@ module.exports = {
|
|
|
155
153
|
DEFAULT_SENSITIVE_FIELDS,
|
|
156
154
|
};
|
|
157
155
|
|
|
158
|
-
|
package/nextjs.js
CHANGED
|
@@ -186,16 +186,6 @@ function registerSecureNow(options = {}) {
|
|
|
186
186
|
const otelLogLevel = String(appConfig.configValue('otel.logLevel', '') || '').toLowerCase();
|
|
187
187
|
const isDevelopmentRuntime = process.env.NODE_ENV === 'development';
|
|
188
188
|
|
|
189
|
-
// @vercel/otel still reads OTel process variables internally. These are
|
|
190
|
-
// derived from credentials JSON; customers do not set them.
|
|
191
|
-
if (isVercel) {
|
|
192
|
-
if (!process.env.OTEL_SERVICE_NAME) process.env.OTEL_SERVICE_NAME = serviceName;
|
|
193
|
-
if (!process.env.OTEL_EXPORTER_OTLP_ENDPOINT) process.env.OTEL_EXPORTER_OTLP_ENDPOINT = endpointBase;
|
|
194
|
-
if (!process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT) process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = tracesUrl;
|
|
195
|
-
const headerString = appConfig.headersToString(headers);
|
|
196
|
-
if (headerString && !process.env.OTEL_EXPORTER_OTLP_HEADERS) process.env.OTEL_EXPORTER_OTLP_HEADERS = headerString;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
189
|
console.log('[securenow] Next.js App -> service.name=%s', serviceName);
|
|
200
190
|
console.log('[securenow] Environment: %s', deploymentEnvironment);
|
|
201
191
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "securenow",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.0",
|
|
4
4
|
"description": "OpenTelemetry instrumentation for Node.js, Next.js, and Nuxt - Send traces and logs to any OTLP-compatible backend",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "register.js",
|
|
@@ -167,8 +167,7 @@
|
|
|
167
167
|
"@opentelemetry/sdk-node": "0.218.0",
|
|
168
168
|
"@opentelemetry/sdk-trace-base": "2.7.1",
|
|
169
169
|
"@opentelemetry/sdk-trace-web": "2.7.1",
|
|
170
|
-
"@opentelemetry/semantic-conventions": "1.41.1"
|
|
171
|
-
"dotenv": "17.2.1"
|
|
170
|
+
"@opentelemetry/semantic-conventions": "1.41.1"
|
|
172
171
|
},
|
|
173
172
|
"optionalDependencies": {
|
|
174
173
|
"@vercel/otel": "2.1.2"
|
package/rate-limits.js
CHANGED
package/register-vite.js
CHANGED
|
@@ -1,12 +1,5 @@
|
|
|
1
|
-
// node_modules/securenow/register-vite.js (CommonJS, for -r)
|
|
2
|
-
'use strict';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
console.log('[securenow] dotenv loaded for Vite preload');
|
|
7
|
-
} catch {
|
|
8
|
-
console.log('[securenow] dotenv not available, continuing without .env');
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
// Trace the Node process (Vite dev/preview server) using your existing Node tracer
|
|
12
|
-
module.exports = require('./web-vite.mjs');
|
|
1
|
+
// node_modules/securenow/register-vite.js (CommonJS, for -r)
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
// Trace the Node process (Vite dev/preview server) using your existing Node tracer
|
|
5
|
+
module.exports = require('./web-vite.mjs');
|
package/register.js
CHANGED
|
@@ -4,17 +4,9 @@
|
|
|
4
4
|
// For ESM apps ("type": "module"), this file auto-registers the
|
|
5
5
|
// OpenTelemetry ESM loader hook via module.register() (Node >=20.6).
|
|
6
6
|
// On older Node versions it falls back to a warning.
|
|
7
|
-
'use strict';
|
|
8
|
-
|
|
9
|
-
// 1.
|
|
10
|
-
// configuration comes from .securenow/credentials.json via app-config.js.
|
|
11
|
-
try {
|
|
12
|
-
require('dotenv').config({ quiet: true });
|
|
13
|
-
} catch (e) {
|
|
14
|
-
// dotenv is optional.
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// 2. Auto-register the ESM loader hook so customers never need --import
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
// 1. Auto-register the ESM loader hook so customers never need --import
|
|
18
10
|
(() => {
|
|
19
11
|
try {
|
|
20
12
|
const fs = require('fs');
|
|
@@ -45,5 +37,5 @@ try {
|
|
|
45
37
|
}
|
|
46
38
|
})();
|
|
47
39
|
|
|
48
|
-
//
|
|
49
|
-
require('./tracing');
|
|
40
|
+
// 2. Run the OTel SDK setup
|
|
41
|
+
require('./tracing');
|
package/resolve-ip.js
CHANGED
|
@@ -6,7 +6,7 @@ const appConfig = require('./app-config');
|
|
|
6
6
|
const LOOPBACK_RE = /^(127\.|::1$|::ffff:127\.)/;
|
|
7
7
|
const PRIVATE_IP_RE = /^(127\.|::1$|10\.|172\.(1[6-9]|2\d|3[01])\.|192\.168\.|169\.254\.|100\.(6[4-9]|[7-9]\d|1[01]\d|12[0-7])\.|f[cd][0-9a-f]{2}:)/i;
|
|
8
8
|
|
|
9
|
-
const trustedProxies = appConfig.
|
|
9
|
+
const trustedProxies = appConfig.listConfig('networking.trustedProxies');
|
|
10
10
|
const trustedProxySet = trustedProxies.length ? new Set(trustedProxies.map(normalizeIp).filter(Boolean)) : null;
|
|
11
11
|
|
|
12
12
|
let _hostIps = null;
|
package/tracing.d.ts
CHANGED
|
@@ -165,7 +165,7 @@ export const loggerProvider: LoggerProvider | null;
|
|
|
165
165
|
* Configuration:
|
|
166
166
|
*
|
|
167
167
|
* Local development reads .securenow/credentials.json first. Run
|
|
168
|
-
* `npx securenow login` to write app identity/
|
|
168
|
+
* `npx securenow login` to write app identity/runtime API key and
|
|
169
169
|
* `npx securenow init` to ensure secure defaults and explanations.
|
|
170
170
|
*
|
|
171
171
|
* Production uses the same file shape. Run
|
package/tracing.js
CHANGED
|
@@ -280,8 +280,8 @@ const endpointBase = resolvedEndpoints.endpointBase;
|
|
|
280
280
|
const tracesUrl = resolvedEndpoints.tracesUrl;
|
|
281
281
|
const logsUrl = resolvedEndpoints.logsUrl;
|
|
282
282
|
|
|
283
|
-
// resolveEndpoints() also adds
|
|
284
|
-
// explicit OTLP headers did not provide
|
|
283
|
+
// resolveEndpoints() also adds app routing and runtime auth headers when
|
|
284
|
+
// explicit OTLP headers did not provide them.
|
|
285
285
|
const headers = resolvedEndpoints.headers;
|
|
286
286
|
|
|
287
287
|
// -------- naming rules --------
|
package/web-vite.mjs
CHANGED
|
@@ -12,21 +12,21 @@ import { FetchInstrumentation } from '@opentelemetry/instrumentation-fetch';
|
|
|
12
12
|
import { XMLHttpRequestInstrumentation } from '@opentelemetry/instrumentation-xml-http-request';
|
|
13
13
|
|
|
14
14
|
// ---- helpers / browser config ----
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
15
|
+
const DEFAULT_BROWSER_CONFIG = Object.freeze({
|
|
16
|
+
config: {
|
|
17
|
+
otel: {
|
|
18
|
+
endpoint: 'https://ingest.securenow.ai',
|
|
19
|
+
tracesEndpoint: null,
|
|
20
|
+
headers: {},
|
|
21
|
+
},
|
|
22
|
+
runtime: {
|
|
23
|
+
deploymentEnvironment: 'production',
|
|
24
|
+
noUuid: null,
|
|
25
|
+
strict: false,
|
|
26
|
+
testSpan: false,
|
|
27
|
+
hideBanner: false,
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
30
|
});
|
|
31
31
|
|
|
32
32
|
function createResource(attributes) {
|
|
@@ -39,15 +39,6 @@ function createResource(attributes) {
|
|
|
39
39
|
throw new Error('Unsupported @opentelemetry/resources version');
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
function legacyViteEnvFallbackEnabled() {
|
|
43
|
-
const raw =
|
|
44
|
-
viteEnv.SECURENOW_ENABLE_LEGACY_ENV ??
|
|
45
|
-
viteEnv.VITE_SECURENOW_ENABLE_LEGACY_ENV ??
|
|
46
|
-
viteEnv.SECURENOW_ALLOW_ENV_CONFIG ??
|
|
47
|
-
viteEnv.VITE_SECURENOW_ALLOW_ENV_CONFIG;
|
|
48
|
-
return /^(1|true|yes)$/i.test(String(raw || '').trim());
|
|
49
|
-
}
|
|
50
|
-
|
|
51
42
|
function getPath(obj, path) {
|
|
52
43
|
if (!obj || !path) return undefined;
|
|
53
44
|
let cur = obj;
|
|
@@ -74,28 +65,27 @@ function toConfigString(value) {
|
|
|
74
65
|
return String(value);
|
|
75
66
|
}
|
|
76
67
|
|
|
77
|
-
function
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const mappedPath = ENV_TO_BROWSER_CONFIG_PATH[String(k).toUpperCase()];
|
|
82
|
-
if (injected) {
|
|
83
|
-
if (mappedPath) {
|
|
84
|
-
const mappedValue = getPath(injected, mappedPath);
|
|
85
|
-
const resolved = toConfigString(mappedValue);
|
|
86
|
-
if (resolved !== undefined) return resolved;
|
|
87
|
-
}
|
|
88
|
-
if (!mappedPath && k in injected) return toConfigString(injected[k]);
|
|
89
|
-
}
|
|
68
|
+
function browserConfig() {
|
|
69
|
+
const injected = globalThis.window && globalThis.window.__SECURENOW__;
|
|
70
|
+
return injected && typeof injected === 'object' ? injected : {};
|
|
71
|
+
}
|
|
90
72
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
73
|
+
function configValue(path, fallback) {
|
|
74
|
+
const injected = getPath(browserConfig(), path);
|
|
75
|
+
if (injected !== undefined && injected !== null && injected !== '') return injected;
|
|
76
|
+
const defaultValue = getPath(DEFAULT_BROWSER_CONFIG, path);
|
|
77
|
+
if (defaultValue !== undefined && defaultValue !== null && defaultValue !== '') return defaultValue;
|
|
78
|
+
return fallback;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function boolConfig(path, fallback = false) {
|
|
82
|
+
const value = configValue(path, fallback);
|
|
83
|
+
if (typeof value === 'boolean') return value;
|
|
84
|
+
if (typeof value === 'number') return value !== 0;
|
|
85
|
+
const text = String(value || '').trim().toLowerCase();
|
|
86
|
+
if (['1', 'true', 'yes', 'on', 'enabled'].includes(text)) return true;
|
|
87
|
+
if (['0', 'false', 'no', 'off', 'disabled'].includes(text)) return false;
|
|
88
|
+
return fallback;
|
|
99
89
|
}
|
|
100
90
|
|
|
101
91
|
function parseHeaders(str) {
|
|
@@ -139,29 +129,30 @@ function normalizeSignalEndpoint(value, signalType) {
|
|
|
139
129
|
|
|
140
130
|
// ---- endpoints (same defaults as tracing.js) ----
|
|
141
131
|
const endpointBase =
|
|
142
|
-
normalizeEndpointBase(
|
|
132
|
+
normalizeEndpointBase(configValue('config.otel.endpoint', 'https://ingest.securenow.ai'));
|
|
143
133
|
const tracesUrl =
|
|
144
|
-
normalizeSignalEndpoint(
|
|
145
|
-
const headers = parseHeaders(
|
|
134
|
+
normalizeSignalEndpoint(configValue('config.otel.tracesEndpoint'), 'traces') || `${endpointBase}/v1/traces`;
|
|
135
|
+
const headers = parseHeaders(toConfigString(configValue('config.otel.headers', {})));
|
|
146
136
|
const deploymentEnvironment =
|
|
147
|
-
|
|
148
|
-
const browserAppKey =
|
|
149
|
-
if (browserAppKey && !headers['x-
|
|
137
|
+
String(configValue('config.runtime.deploymentEnvironment', 'production'));
|
|
138
|
+
const browserAppKey = toConfigString(configValue('app.key'));
|
|
139
|
+
if (browserAppKey && !headers['x-securenow-app-key']) headers['x-securenow-app-key'] = browserAppKey;
|
|
150
140
|
if (deploymentEnvironment && !headers['x-securenow-environment']) headers['x-securenow-environment'] = deploymentEnvironment;
|
|
151
141
|
|
|
152
142
|
// ---- naming rules (mirrors tracing.js) ----
|
|
153
|
-
const rawBase = (
|
|
143
|
+
const rawBase = (toConfigString(configValue('app.key')) || toConfigString(configValue('app.name')) || '').trim().replace(/^['"]|['"]$/g, '');
|
|
154
144
|
const baseName = rawBase || null;
|
|
155
145
|
// Default to no suffix whenever a baseName is resolved: the dashboard filters
|
|
156
146
|
// service.name by exact match, and browsers have no PM2 cluster problem
|
|
157
147
|
// (each tab has its own service.instance.id). Explicit config.runtime.noUuid=false
|
|
158
148
|
// still re-enables the suffix if someone really wants it.
|
|
159
|
-
const noUuidEnv =
|
|
149
|
+
const noUuidEnv = configValue('config.runtime.noUuid');
|
|
160
150
|
const noUuid =
|
|
161
151
|
(noUuidEnv !== undefined && noUuidEnv !== '')
|
|
162
152
|
? /^(1|true)$/i.test(String(noUuidEnv).trim())
|
|
163
153
|
: !!baseName;
|
|
164
|
-
const strict =
|
|
154
|
+
const strict = boolConfig('config.runtime.strict', false);
|
|
155
|
+
const hostedSecureNowIngest = /^https:\/\/ingest\.securenow\.ai(?:\/|$)/i.test(tracesUrl);
|
|
165
156
|
|
|
166
157
|
function uuidv4() {
|
|
167
158
|
if (typeof crypto !== 'undefined' && crypto.randomUUID) {
|
|
@@ -195,6 +186,12 @@ if (baseName) {
|
|
|
195
186
|
}
|
|
196
187
|
}
|
|
197
188
|
|
|
189
|
+
if (!disabled && hostedSecureNowIngest) {
|
|
190
|
+
disabled = true;
|
|
191
|
+
// eslint-disable-next-line no-console
|
|
192
|
+
console.warn('[securenow/web-vite] Direct browser OTLP ingestion to SecureNow is disabled in v8.0 until browser-safe auth is available. Use the server-side SDK runtime credentials path.');
|
|
193
|
+
}
|
|
194
|
+
|
|
198
195
|
const instancePrefix = baseName || 'securenow';
|
|
199
196
|
const serviceInstanceId = `${instancePrefix}-${uuidv4()}`;
|
|
200
197
|
|
|
@@ -203,10 +200,10 @@ try {
|
|
|
203
200
|
// eslint-disable-next-line no-console
|
|
204
201
|
console.log(
|
|
205
202
|
'[securenow] web preload loaded app.key=%s app.name=%s config.runtime.noUuid=%s config.runtime.strict=%s → service.name=%s instance.id=%s',
|
|
206
|
-
JSON.stringify(
|
|
207
|
-
JSON.stringify(
|
|
208
|
-
JSON.stringify(
|
|
209
|
-
JSON.stringify(
|
|
203
|
+
JSON.stringify(configValue('app.key')),
|
|
204
|
+
JSON.stringify(configValue('app.name')),
|
|
205
|
+
JSON.stringify(configValue('config.runtime.noUuid')),
|
|
206
|
+
JSON.stringify(configValue('config.runtime.strict')),
|
|
210
207
|
serviceName,
|
|
211
208
|
serviceInstanceId
|
|
212
209
|
);
|
|
@@ -229,7 +226,7 @@ export function startSecurenowWeb() {
|
|
|
229
226
|
[S.SERVICE_NAME]: serviceName,
|
|
230
227
|
[S.SERVICE_INSTANCE_ID]: serviceInstanceId,
|
|
231
228
|
[S.DEPLOYMENT_ENVIRONMENT]: deploymentEnvironment,
|
|
232
|
-
[S.SERVICE_VERSION]:
|
|
229
|
+
[S.SERVICE_VERSION]: toConfigString(configValue('app.version')) || undefined,
|
|
233
230
|
}),
|
|
234
231
|
spanProcessors: [new BatchSpanProcessor(exporter)],
|
|
235
232
|
});
|
|
@@ -250,8 +247,7 @@ export function startSecurenowWeb() {
|
|
|
250
247
|
],
|
|
251
248
|
});
|
|
252
249
|
|
|
253
|
-
|
|
254
|
-
if (String(env('SECURENOW_TEST_SPAN')) === '1') {
|
|
250
|
+
if (boolConfig('config.runtime.testSpan', false)) {
|
|
255
251
|
import('@opentelemetry/api').then(api => {
|
|
256
252
|
const tracer = api.trace.getTracer('securenow-smoke');
|
|
257
253
|
const span = tracer.startSpan('securenow.startup.smoke.web'); span.end();
|
|
@@ -265,7 +261,7 @@ export function startSecurenowWeb() {
|
|
|
265
261
|
// ---- Free trial banner (browser DOM injection) ----
|
|
266
262
|
function injectFreeTrialBanner() {
|
|
267
263
|
const FREE_TRIAL_HOSTS = ['ingest.securenow.ai', 'freetrial.securenow.ai'];
|
|
268
|
-
const hideBanner =
|
|
264
|
+
const hideBanner = boolConfig('config.runtime.hideBanner', false);
|
|
269
265
|
if (hideBanner || !FREE_TRIAL_HOSTS.some(host => endpointBase.includes(host))) return;
|
|
270
266
|
if (typeof document === 'undefined') return;
|
|
271
267
|
|