Commit Graph

257 Commits

Author SHA1 Message Date
9b7878a623 feat(navigation): bind binders accept (realtime, realtimeRegistry) params
Extend bindProductionNavigation and bindDevSeedNavigation to 7-arg signatures.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 22:41:16 +02:00
579c5911fd feat(marketing-pages): bind binders accept (realtime, realtimeRegistry) params
Extend bindProductionMarketingPages and bindDevSeedMarketingPages to 7-arg signatures.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 22:41:13 +02:00
f85b0891ee feat(media): bind binders accept (realtime, realtimeRegistry) params
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
Extend bindProductionMedia and bindDevSeedMedia to 7-arg signatures.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 22:41:10 +02:00
1f12e6af12 feat(blog): bind binders accept (realtime, realtimeRegistry) params
Extend bindProductionBlog and bindDevSeedBlog to 7-arg signatures.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 22:41:07 +02:00
7e1d2d5c4b feat(auth): bind binders accept (realtime, realtimeRegistry) params
Extend bindProductionAuth and bindDevSeedAuth to 7-arg signatures.
Fix RecordingRealtimeBroadcaster scope type to structurally match ChannelScope.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 22:41:04 +02:00
c882614153 test(core-eslint): extend anchor-presence guard for realtime anchors
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 22:07:21 +02:00
f5b0e8e6ae chore(navigation): add // <gen:realtime-*> anchor comments
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 22:07:08 +02:00
2939b94302 chore(marketing-pages): add // <gen:realtime-*> anchor comments
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 22:06:45 +02:00
4fd95921f0 chore(media): add // <gen:realtime-*> anchor comments
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 22:06:14 +02:00
8367cb184e chore(blog): add // <gen:realtime-*> anchor comments
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 22:05:51 +02:00
03a0900688 chore(auth): add // <gen:realtime-*> anchor comments
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 22:05:27 +02:00
122a81b2ca feat(core-eslint): rule no-realtime-handler-reexport
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 22:01:03 +02:00
77467de702 feat(core-eslint): rule no-direct-socket-io
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 21:59:52 +02:00
928357f221 feat(core-testing): RecordingRealtimeBroadcaster (local-type-alias pattern) 2026-05-08 21:56:18 +02:00
228cfb57c0 fix(core-realtime): address Phase 2 code review (typing, error handling, params)
- Type socket.data.user via AppSocketData/AppSocket generics (no more any)
- Wrap Gate 1 authenticator call in try/catch so exceptions reject the
  connection with connect_error instead of being swallowed
- Fix Gate 3 userScoped channel authorize: derive params.userId from the
  authenticated socket user so owner-inbound is accepted
- Await io.close(callback) in stop() to ensure full shutdown
- Remove unused httpServer field from constructor (io already holds the ref)
- Extract CHANNEL_ROOM_PREFIX/channelRoom helper to channel-room.ts;
  replace three `ch:${name}` magic strings; re-export from index
- Add JSDoc to ChannelScope explaining userScoped params/template convention
- Fix "allows subscribe + invokes handler with ctx" test: hoist received
  outside beforeEach and assert ctx shape
- New test: rejects connection when authenticator throws
- New test: userScoped channel accepts inbound from owner, rejects from anon
2026-05-08 21:52:52 +02:00
964fabf796 fix(core-realtime): remove unused PLACEHOLDER var and ClientSocket import (lint) 2026-05-08 21:16:44 +02:00
d4a3f95938 feat(core-realtime): public barrel 2026-05-08 21:16:22 +02:00
2939ff8bb5 feat(core-realtime): SocketIORealtimeServer (4 lifecycle gates) 2026-05-08 21:16:03 +02:00
9d04bdc65b feat(core-realtime): SocketIORealtimeBroadcaster 2026-05-08 21:15:07 +02:00
86b9418758 feat(core-realtime): IRealtimeServer interface 2026-05-08 21:14:43 +02:00
5e57c66140 feat(core-realtime): InMemoryRealtimeBroadcaster (test/dev impl) 2026-05-08 21:14:33 +02:00
6c5484b874 feat(core-realtime): RealtimeHandlerRegistry 2026-05-08 21:14:11 +02:00
f072435024 feat(core-realtime): authorize function (4 scope kinds) 2026-05-08 21:13:48 +02:00
0771601571 feat(core-realtime): channel-template matcher (placeholder extraction) 2026-05-08 21:13:18 +02:00
691b4942d5 feat(core-realtime): IRealtimeAuthenticator interface 2026-05-08 21:12:56 +02:00
caf86abbe5 feat(core-realtime): IRealtimeHandler + IInboundDescriptor types 2026-05-08 21:12:47 +02:00
795511b5b3 feat(core-realtime): IRealtimeBroadcaster interface + symbol registry 2026-05-08 21:12:36 +02:00
7e922bc406 feat(core-realtime): RealtimeChannelDescriptor + defineRealtimeChannel 2026-05-08 21:12:24 +02:00
1a0e3c20ff chore(core-realtime): align scaffold style with core-events (review polish) 2026-05-08 21:09:50 +02:00
fd76aa445d chore(core-eslint,turbo): tag @repo/core-realtime as core
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 20:59:01 +02:00
bbdb456aa0 chore(core-realtime): scaffold package
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 20:58:05 +02:00
5a2234f7ad docs: refresh per-package AGENTS.md + di-explainer to current binders
Six per-package AGENTS.md tables and the di-explainer wiring trace all
showed pre-ADR-014 binder shapes. Refreshed to the post-ADR-015
reality:

- Per-package "Public exports" tables now show the
  (config, tracer, logger, bus, queue) production signature and the
  (tracer, logger, bus, queue) dev-seed companion. auth and
  marketing-pages also list their newly-public ./di/container,
  ./di/symbols, and (marketing-pages only) ./services/mailer +
  ./services/recording-mailer subpaths.
- di-explainer's wiring trace adds the resolveEventsAndJobs* step in
  bindAll(), the (config, tracer, logger, bus, queue) binder
  signature, and the // <gen:event-handlers> / // <gen:jobs>
  injection sites.

No code change; pre-existing AGENTS.md staleness predates ADR-014 +
ADR-015 — this commit catches both up.
2026-05-08 17:51:35 +02:00
a98e41d080 chore: workspace green check (Task 56)
Three issues uncovered by the full pnpm typecheck/test/boundaries pass
and resolved here:

- core-testing was importing IEventBus / IJobQueue from core-events /
  core-shared, creating two boundary violations (tooling → core) and a
  build-graph cycle. Inlined the type aliases (mirroring how
  RecordingTracer / RecordingLogger handle ITracer / ILogger).
  recording-event-bus.test.ts replaces defineEvent() with an inline
  descriptor literal so no runtime import is needed either. core-events
  and core-shared are removed from core-testing dependencies.

- turbo.json: typecheck and test no longer dependsOn ^typecheck / ^build.
  Each package's tsc / vitest resolves cross-package types via
  node_modules independently, and dropping the topological dep avoids the
  spurious cycle warning that appeared once core-testing started
  importing core-events / core-shared.

- turbo.json: feature.dependencies.allow gains "feature". Cross-feature
  event flow (ADR-015) requires a consumer feature to import the
  publisher's event contract directly. The dangerous form (importing
  the publisher's handler/use-case/repo) is still blocked by E1's
  no-handler-reexport ESLint rule and the missing public exports.

- TaskConfig<"slug-string"> → TaskConfig<{ input; output }> in the gen
  job task template (and the shipped send-welcome-email.task.ts) since
  runtime-generated slugs aren't keys of TypedJobs['tasks'].
2026-05-08 17:21:47 +02:00
04899de98c test(web-next): e2e cross-feature sign-up→welcome-email flow
End-to-end proof-of-life. bindAllDevSeed wires InMemoryEventBus +
InMemoryJobQueue across all features. signUpController publishes
auth.user.signed-up; marketing-pages' handler enqueues
marketing-pages.send-welcome-email; the in-memory queue dispatches
the wrapped job which records on RecordingMailerService.

Adds ./di/container, ./di/symbols, ./services/mailer, and
./services/recording-mailer to auth + marketing-pages exports so
the e2e test can resolve from the per-feature containers without
deep-importing.
2026-05-08 16:37:37 +02:00
7e844c646d feat(marketing-pages): sendWelcomeEmail job + handler enqueues it
sendWelcomeEmailJob takes IMailerService, validates the typed input
(userId + email), and delegates to mailer.sendWelcome. The
onAuthUserSignedUpHandler now takes IJobQueue and enqueues
"marketing-pages.send-welcome-email" with the event payload.

Both binders bind a RecordingMailerService at the IMailerService
symbol (production placeholder until a real adapter ships) and pass
mailer / queue into the wrapped factories. Dev-seed additionally
queue.register()s the slug so the in-memory queue dispatches via
the wrapped job; production relies on the generated Payload event-task
to resolve the wrapped handler from the container.
2026-05-08 16:35:45 +02:00
6b57a34c0c feat(marketing-pages): subscribe to auth.user.signed-up
Generated handler + Payload event-task via gen event consume,
threaded through symbols / both binders / cms re-export at the
configured anchors. bus.subscribe wires the in-memory delivery in
dev-seed; the __events.auth.user.signed-up.marketing-pages Payload
task closes the production-bus loop.

Also fixes two generator-level issues found during Phase 8:
- Drop publisher prompt's `when` clause so --args can supply the
  4th positional argument (Plop limitation: --args cannot bypass
  conditional prompts). Validate runs only in consume mode.
- Switch event-task.ts.hbs from TaskConfig<"slug-string"> to
  TaskConfig<{ input: ...; output: object }> since runtime-generated
  event slugs are not keys of TypedJobs['tasks'].
2026-05-08 16:33:14 +02:00
c1b8a7e434 feat(auth): signUp publishes userSignedUpEvent
signUpUseCase now takes an IEventBus and publishes userSignedUpEvent
after creating the user (synthesizing email from username since auth
is username-based). Use case mocks-default in module.ts get a fresh
InMemoryEventBus per resolution; bind-production / bind-dev-seed wire
the shared bus passed by bindAll. Tests updated to inject
RecordingEventBus, including a new test that asserts publish on
success and silence on failure.
2026-05-08 16:28:21 +02:00
7f63adf740 feat(auth): userSignedUpEvent contract 2026-05-08 16:24:12 +02:00
1c13b757ed feat(marketing-pages): RecordingMailerService 2026-05-08 16:23:32 +02:00
73f6db54b3 feat(marketing-pages): IMailerService interface (proof-of-life) 2026-05-08 16:23:00 +02:00
2b4e576b0d feat(navigation): bind binders accept (bus, queue) params 2026-05-08 16:07:05 +02:00
4e77134ff6 feat(marketing-pages): bind binders accept (bus, queue) params 2026-05-08 16:05:49 +02:00
a9100de052 feat(media): bind binders accept (bus, queue) params 2026-05-08 16:04:37 +02:00
d6fe37450a feat(blog): bind binders accept (bus, queue) params 2026-05-08 15:17:40 +02:00
b0bd4c0bb3 feat(auth): bind binders accept (bus, queue) params 2026-05-08 15:16:16 +02:00
8b3b118bb0 test(core-eslint): anchor-presence CI guard for // <gen:*> comments
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 12:49:35 +02:00
bd1610a888 chore(navigation): add // <gen:*> anchor comments for event/job generators
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 12:48:24 +02:00
3c0eb34f5e chore(marketing-pages): add // <gen:*> anchor comments for event/job generators
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 12:47:40 +02:00
b672506c30 chore(media): add // <gen:*> anchor comments for event/job generators
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 12:47:04 +02:00
2506c2676b chore(blog): add // <gen:*> anchor comments for event/job generators
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 12:46:31 +02:00