Skip to content
Open
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,8 @@ jobs:
STRIPE_SECRET_KEY: ""
STRIPE_WEBHOOK_SECRET: ""
run: npm --workspace=apps/web test -- --reporter=default --reporter=json --outputFile.json="$RUNNER_TEMP/web-vitest-report.json"
- name: Root MCP dependency security and type regressions
run: npm run test:mcp-security
- name: Retain machine-readable test evidence
if: always()
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
Expand Down
6 changes: 3 additions & 3 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@
"@google/genai": "^2.31.0",
"@google/generative-ai": "^0.24.1",
"@opentelemetry/api": "^1.10.0",
"@opentelemetry/core": "2.11.0",
"@opentelemetry/core": "3.0.0",
"@opentelemetry/exporter-trace-otlp-http": "^0.300.0",
"@opentelemetry/instrumentation": "0.300.0",
"@opentelemetry/resources": "2.11.0",
"@opentelemetry/sdk-trace-base": "2.12.0",
"@opentelemetry/resources": "3.0.0",
"@opentelemetry/sdk-trace": "3.0.0",
"@opentelemetry/semantic-conventions": "1.44.0",
"@radix-ui/react-label": "^2.1.17",
"@radix-ui/react-separator": "^1.2.0",
Expand Down
68 changes: 68 additions & 0 deletions apps/web/src/lib/__tests__/opentelemetry-compatibility.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { createRequire } from 'node:module';
import { join } from 'node:path';
import { describe, expect, it } from 'vitest';

// Use Node's installed-package resolution, including transitive dependencies.
// Mocking these imports would hide the hoisted API mismatch this guards against.
const fromWeb = createRequire(join(process.cwd(), 'package.json'));

describe('installed OpenTelemetry compatibility', () => {
it('initializes instrumentation with the logging API it actually resolves', () => {
const { InstrumentationBase } = fromWeb('@opentelemetry/instrumentation') as
typeof import('@opentelemetry/instrumentation');
class ProbeInstrumentation extends InstrumentationBase {
protected init() { return []; }
}

const probe = new ProbeInstrumentation('eventrelay-compatibility-test', '1.0.0', {
enabled: false,
});
expect(probe.isEnabled()).toBe(false);
probe.disable();
});

it('records and exports a span through the maintained tracing SDK', async () => {
const { TracerProvider, SimpleSpanProcessor, InMemorySpanExporter } =
fromWeb('@opentelemetry/sdk-trace') as typeof import('@opentelemetry/sdk-trace');
const { resourceFromAttributes } = fromWeb('@opentelemetry/resources') as
typeof import('@opentelemetry/resources');
const exporter = new InMemorySpanExporter();
const provider = new TracerProvider({
resource: resourceFromAttributes({ 'service.name': 'eventrelay-test' }),
spanProcessors: [new SimpleSpanProcessor({ exporter })],
});

try {
const span = provider.getTracer('compatibility-test').startSpan('video-processing');
span.setAttribute('video.id', 'synthetic-video');
span.end();
await provider.forceFlush();

const spans = exporter.getFinishedSpans();
expect(spans).toHaveLength(1);
expect(spans[0].name).toBe('video-processing');
expect(spans[0].attributes['video.id']).toBe('synthetic-video');
expect(spans[0].resource.attributes['service.name']).toBe('eventrelay-test');
} finally {
await provider.shutdown();
}
});

it('shares the logging-capable API with the exporter and its SDK dependencies', () => {
const api = fromWeb('@opentelemetry/api') as typeof import('@opentelemetry/api');
expect(typeof api.logs.getLogger).toBe('function');
const fromExporter = createRequire(fromWeb.resolve('@opentelemetry/exporter-trace-otlp-http'));
const fromTransformer = createRequire(fromExporter.resolve('@opentelemetry/otlp-transformer'));

for (const packageName of [
'@opentelemetry/core',
'@opentelemetry/resources',
'@opentelemetry/sdk-trace',
'@opentelemetry/sdk-logs',
'@opentelemetry/sdk-metrics',
]) {
const fromPackage = createRequire(fromTransformer.resolve(packageName));
expect(fromPackage('@opentelemetry/api'), packageName).toBe(api);
}
});
});
Loading
Loading