Commit Graph

315 Commits

Author SHA1 Message Date
82d80014bf fix(otel): address lint and test regressions from C1/C2 fixes
- Prefix unused opts param with _opts in bindOtelInstrumentation (ESLint)
- Extend IPv6 regex to cover prefix::suffix form (e.g. 2001:0db8::1) so
  the IPv6 scrub test passes correctly
- Delete orphaned sentry-pii-scrubber.test.ts files from apps/cms and
  apps/web-tanstack that imported the deleted sentry/scrub module (broke
  typecheck; the OTel-layer replacement tests are in pii-scrub-processor.test.ts)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 12:42:38 +02:00
9acf16f399 chore: address Phase 5 review polish (test descriptions, version conflict comment, mock cleanup)
I3: bind-production.test.ts instrumentation orthogonality tests updated to use
bindOtelInstrumentation as primary name (bindSentryInstrumentation alias still
wired in mock setup for deprecation-alias coverage, not in assertions).
I4: as never cast in init-server-node.ts annotated with explanation of the
sdk-trace-base / sdk-node TypeScript version conflict that necessitates it.
I5: SentryLogRecordProcessor removed from @sentry/opentelemetry mock in
no-instrumentation.ts — that class does not exist in v10.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 12:40:11 +02:00
7c74a1c9e1 fix(otel): scrub IP addresses in attribute values + log bodies (R32 compliance)
PII_KEY_SUBSTRINGS extended with all OTel HTTP semconv IP attribute keys
(http.client_ip, client.address, net.peer.ip, etc.) so they are key-redacted.
scrubValue() added to pii-scrub-processor.ts applies IPV4_REGEX / IPV6_REGEX
replacement for attribute values whose keys are not PII-keyed, and for log
record bodies that pass the substring check. Closes the gap left by deletion
of the old beforeSend value-level IP scrubbers. 5 new tests added.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 12:39:22 +02:00
4ea9a5c38e fix(otel): consolidate to single OTel SDK init at instrumentation.register hook
All three apps' instrumentation.ts files now call initOtelServerNode directly
instead of initSentryServer/initSentryServerNode, closing the startup window
where @sentry/nextjs auto-instrumentation could send unscrubbed errors before
bindAll() fires. bindOtelInstrumentation no longer calls initOtelServerNode
(SDK init belongs at app boot, binding at request scope). Orphaned sentry/
init-server*.ts files deleted; their package.json subpath exports removed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 12:38:17 +02:00
e43e03cdee docs: refresh architecture references for OTel migration 2026-05-11 12:18:44 +02:00
8bedb649ca refactor(core-testing): no-sentry → no-instrumentation (mocks OTel too) 2026-05-11 12:14:18 +02:00
bd95315a44 refactor(core-eslint): finalize OTel + Sentry import allowlist (R40 + R52) 2026-05-11 12:12:57 +02:00
301e0ff3f8 refactor(core-shared): delete Sentry scrub + orphaned server-init files (replaced by OTel processors) 2026-05-11 12:12:12 +02:00
ad609f8f01 feat(core-shared): wire PII scrub processors FIRST in OTel pipeline 2026-05-11 12:09:11 +02:00
6ec5aeb31f feat(core-shared): PII scrub processors for spans + log records 2026-05-11 12:08:20 +02:00
cdfca850ac feat(core-shared): enable OTel auto-instrumentations (http + undici + pg) 2026-05-11 12:06:00 +02:00
be8103619e feat(core-shared): add OTel auto-instrumentation deps (http + undici + pg) 2026-05-11 12:05:41 +02:00
d5f0f51b75 feat(core-shared): MetricsProtocol + BindContext.metrics? field 2026-05-11 12:02:06 +02:00
0850711986 feat(core-shared): wire IMetrics into DI bindings 2026-05-11 12:01:01 +02:00
f2627890be feat(core-testing): RecordingMetrics test double 2026-05-11 11:59:46 +02:00
9835752c21 feat(core-shared): OtelMetrics impl using @opentelemetry/api metrics 2026-05-11 11:59:04 +02:00
e11fd7c897 feat(core-shared): IMetrics interface + NoopMetrics impl 2026-05-11 11:57:56 +02:00
2cf1c00f93 feat(core-shared): add @opentelemetry/sdk-metrics dep 2026-05-11 11:57:31 +02:00
5c9cba318a refactor(core-shared): delete SentryLogger (replaced by OtelLogger)
Some checks failed
CI / typecheck + lint + boundaries + test + build (push) Has been cancelled
CI / Playwright e2e (push) Has been cancelled
CI / Storybook smoke tests (push) Has been cancelled
Sentry PII guard (R31) / pii-guard (push) Has been cancelled
Removes sentry-logger.ts and its test now that OtelLogger is the active
ILogger impl in bind-otel-instrumentation.ts. Updates the binder test to
assert OtelLogger (not SentryLogger) is bound. Fixes TypeScript errors:
SentryLogRecordForwarder registers directly as LogRecordProcessor (not
wrapped in BatchLogRecordProcessor which expects a LogRecordExporter);
severityNumber undefined guard added.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 11:54:54 +02:00
ad64009e86 feat(core-shared): SentryLogRecordForwarder + wire OtelLogger in OTel pipeline
Adds SentryLogRecordForwarder (LogRecordProcessor impl) to sentry-bridge.ts
that forwards OTel log records to Sentry via captureException/captureMessage.
Wires it as a BatchLogRecordProcessor in init-server-node.ts. Replaces
SentryLogger with OtelLogger in bind-otel-instrumentation.ts. 7 new bridge
tests pass alongside the existing 25 tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 11:53:23 +02:00
5e795fd7ab feat(core-shared): OtelLogger impl using @opentelemetry/api-logs
Implements ILogger via OTel Logs API. captureException emits an ERROR
log record with exception.* semantic conventions and double-report guard;
captureMessage maps ILogger levels to OTel SeverityNumber; addBreadcrumb
attaches span events; setUser sets user.id span attribute. 15 tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 11:49:22 +02:00
3f40ca773b feat(core-shared): add @opentelemetry/api-logs + sdk-logs deps
Adds @opentelemetry/api-logs ^0.55.0 and @opentelemetry/sdk-logs ^0.55.0
to core-shared dependencies in preparation for OtelLogger (Phase 3).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 11:48:23 +02:00
4b390e028d refactor(core-shared): delete SentryTracer (replaced by OtelTracer)
sentry/sentry-tracer.ts and its test removed. OtelTracer is now the active
ITracer implementation. Spans flow to Sentry via @sentry/opentelemetry's
SentrySpanProcessor wired in bindOtelInstrumentation → initOtelServerNode.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 11:43:26 +02:00
53bfe727b4 refactor(core-shared): rename bindSentryInstrumentation → bindOtelInstrumentation
git mv bind-sentry-instrumentation → bind-otel-instrumentation; function
renamed; new impl calls initOtelServerNode and binds OtelTracer (SentryLogger
kept for Phase 3). Barrel re-exports both new name and deprecated alias
bindSentryInstrumentation for one release. ESLint allowlist updated to the
new filename. init-server-node opts gains release? field.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 11:42:07 +02:00
b61e9d2091 feat(core-shared): OtelTracer impl using @opentelemetry/api
Implements OtelTracer as ITracer replacement for SentryTracer. Uses
@opentelemetry/api's trace.getTracer + startActiveSpan, maps span.op to
a span attribute, catches exceptions via recordException + setStatus(ERROR),
and filters null attribute values. Five Vitest tests covering name/attributes,
nesting, exception recording, status mapping, and null filtering.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 11:40:43 +02:00
4c628022ce fix(core-shared): align OTel type imports to sdk-node re-exports to resolve version conflict 2026-05-11 11:28:07 +02:00
f94f09a9fa feat(core-shared): OTel barrel + ESLint allowlist for SDK packages 2026-05-11 11:25:29 +02:00
e85b8b12cf feat(core-shared): OTel NodeSDK init helper with Sentry exporter wiring 2026-05-11 11:24:55 +02:00
3a32838c71 feat(core-shared): Sentry-as-OTel-exporter bridge module 2026-05-11 11:23:49 +02:00
12aeb8bf37 feat(core-shared): OTel resource builder 2026-05-11 11:23:19 +02:00
80e765c074 feat(core-shared): add OpenTelemetry SDK dependencies 2026-05-11 11:22:09 +02:00
ee069574ba fix: address final-review polish (docs + comments + test coverage)
- AGENTS.md bind-production code block: shows the slim default state
  (no @repo/core-events / @repo/core-realtime imports, BindProductionContext
  with no generic args) with a comment pointing to the scaffold workflow.
  The previous block showed a fully-wired post-scaffold state without
  signaling that none of those packages exist in main.
- bind-protocols.test.ts: top-of-file comment clarifies what these tests
  actually verify (protocol shapes have required methods) vs what the
  spec text might suggest (full assignability of optional packages'
  interfaces — that's verified by the e2e reconstruction tests, not here).
- core-package-generator.md: drops two stale "Until Phases 3-6 land"
  parentheticals — the phases shipped.
- config.test.ts: extends the choices assertion to cover all 4 names
  (realtime, events, trpc, ui).
- marketing-pages bind-* comments: reverse the inverted optional/required
  language. queue (IJobQueue) is from core-shared and always present;
  bus is the optional one (from @repo/core-events when scaffolded).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 15:01:40 +02:00
a4c8f710a6 refactor: remove core-ui from main (scaffoldable via gen core-package ui)
Removal across all three consumers:
- apps/storybook: strips @repo/core-ui dep, clears stories glob (now []),
  removes globals.css import from preview.ts
- apps/web-next: strips @repo/core-ui dep + transpilePackages entry
- apps/web-tanstack: strips @repo/core-ui dep
- packages/core-ui: deleted entirely (28 files)

No app pages needed surgery — neither web-next nor web-tanstack source
files imported @repo/core-ui directly. The storybook app referenced it
only via the stories glob and the globals.css preview import.

Gates: 40/40 tasks successful, all 4 e2e byte-identical reconstructions
pass (realtime, events, trpc, ui).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-09 14:21:04 +02:00
1967cb36ec docs: trpc now optional — prerequisite notes + conditional HTML
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-09 14:13:12 +02:00
c8116ac3f4 refactor: remove core-trpc from main (scaffoldable via gen core-package trpc)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-09 14:10:48 +02:00
a9f27f0d7e refactor: remove core-events from main (scaffoldable via gen core-package events)
- Delete packages/core-events/ (15 files)
- Strip @repo/core-events from all 5 feature package.json + apps/web-next/package.json
- Strip @repo/core-events from apps/web-next/next.config.mjs transpilePackages
- Strip E1 + J no-restricted-syntax blocks from core-eslint/base.js (anchor remains)
- Update bind-production.ts: drop bus construction + IEventBus import; rename
  resolveEventsAndJobsProduction → resolveJobsProduction (queue only),
  resolveEventsAndJobsDevSeed → resolveJobsDevSeed (queue only);
  ctx no longer has bus field; BindProductionContext generic arg narrowed
- Update bind-production.test.ts: assert ctx.bus is undefined, drop
  PayloadJobsEventBus/InMemoryEventBus instanceof checks
- Update sign-up-welcome-email.test.ts: assert mailer stays empty without bus
- Inline userSignedUpEvent in auth (drop defineEvent import from core-events)
- Drop InMemoryEventBus fallback from auth/di/module.ts

Feature binders' bus?.subscribe/publish calls remain as no-ops. Scaffold
@repo/core-events back via: pnpm turbo gen core-package events

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-09 14:00:35 +02:00
2266429efd feat(core-eslint): anchor for events rules splice
Add // <gen:events-rules> anchor to base.js near the E1 + J
no-restricted-syntax blocks, and assert it in anchors.test.js.
After core-events removal the anchor remains as the splice point
for pnpm turbo gen core-package events.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-09 13:52:23 +02:00
57b2ff5191 refactor: remove core-realtime from main (scaffoldable via gen core-package realtime) 2026-05-09 13:45:52 +02:00
c4035e912e feat(core-eslint): anchors for realtime rules splice 2026-05-09 13:28:35 +02:00
723729dd9e fix: address Phase 1 code-quality review findings
- Generator feature templates emit ctx-arg signatures + updated checklist
- signUpUseCase test for bus=undefined path
- di-explainer.html: bind-dev-seed no-arg → ctx
- data-flow-explainer.html: tradeoff card → ctx
- BindContextBase no longer exported
- CLAUDE.md binder bullet: drop vestigial cast guidance

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-09 13:17:04 +02:00
ca2e7d8c10 fix: address Phase 1 spec review findings
- di-explainer.html: update stale JS data strings from positional-arg
  form (bindAllProduction(config), bindProductionBlog(config,tracer,...))
  to ctx-arg form (bindAllProduction(deps), bindProductionBlog(ctx)) with
  a note on ctx shape.
- auth/sign-up.use-case: change bus param from IEventBus to
  EventBusProtocol|undefined; guard bus.publish with if(bus) so the use
  case is safe when core-events is absent (Phase 3+).
- auth/bind-production + bind-dev-seed: drop as IEventBus cast and unused
  IEventBus import; ctx.bus is now passed directly (typed as
  EventBusProtocol|undefined).
- marketing-pages/bind-production + bind-dev-seed: drop as IJobQueue cast
  and unused IJobQueue import; wrap event-handler DI block in if(queue)
  guard so the handler is only bound when core-jobs is wired.
- core-shared/src/index.ts: add `export * from "./di"` as the plan
  specified (subpath export alone is no longer the only access path).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-09 13:02:36 +02:00
1e8b3f2364 docs: BindContext binder shape across architecture + per-feature AGENTS 2026-05-09 12:49:55 +02:00
3911405102 refactor(media): binders take BindContext arg 2026-05-09 12:44:30 +02:00
a439038748 refactor(navigation): binders take BindContext arg 2026-05-09 12:43:22 +02:00
fe6c41b69d refactor(marketing-pages): binders take BindContext arg 2026-05-09 12:42:29 +02:00
fe85976440 refactor(blog): binders take BindContext arg 2026-05-09 12:40:58 +02:00
ab8ca08307 refactor(auth): binders take BindContext arg 2026-05-09 12:39:50 +02:00
f4942098f1 feat(core-realtime): IRealtimeHandlerRegistry extends RealtimeRegistryProtocol 2026-05-09 12:37:38 +02:00
ebcce46681 feat(core-realtime): IRealtimeBroadcaster extends RealtimeBroadcasterProtocol 2026-05-09 12:37:26 +02:00
07fa35cd0b feat(core-events): IEventBus extends EventBusProtocol 2026-05-09 12:36:38 +02:00