Commit Graph

80 Commits

Author SHA1 Message Date
0c5ad08dcd feat(core-audit): scaffold optional package (no impls yet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 16:10:58 +02:00
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
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
05524dfcea chore(web-next): remove legacy Sentry scrubber test (covered by OTel processor tests)
The sentry-pii-scrubber.test.ts file tested the now-deleted sentry/scrub.ts
module. PII scrubbing is now validated in core-shared/otel/pii-scrub-processor.test.ts
at the correct layer.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 12:22:42 +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
149f91255c refactor(apps): call sites use bindOtelInstrumentation by name
apps/web-next/bind-production.ts imports bindOtelInstrumentation instead
of bindSentryInstrumentation. Test mock tracks both names via the same
spy so existing assertions on bindSentryInstrumentation still pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 11:43:03 +02:00
ae456a5436 docs: ui now optional — prerequisite notes + conditional HTML
- AGENTS.md (root): marks core-ui as optional in the package table and
  boundary rules; points per-package docs to the .hbs template
- apps/storybook/AGENTS.md: rewrites around no-core-ui-by-default;
  stories glob and globals.css import described as post-scaffold steps
- apps/web-next/AGENTS.md: cross-reference updated to template file
- apps/web-tanstack/AGENTS.md: cross-reference updated to template file
- docs/architecture/data-flow-explainer.html: core-ui bullet notes
  optional status + generator command

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-09 14:23:24 +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
57b2ff5191 refactor: remove core-realtime from main (scaffoldable via gen core-package realtime) 2026-05-09 13:45:52 +02:00
d5c965078c test(web-next): bind-production tests assert ctx-shape arg 2026-05-09 12:46:29 +02:00
2854023d13 refactor(web-next): aggregator builds BindContext once 2026-05-09 12:46:27 +02:00
f8013451de fix(realtime): post-review polish from final branch review
Five fixes surfaced by the branch-wide code review on the realtime layer:

- server.ts: replace dynamic `import("@repo/auth/di/container")` with a
  static top-of-file import. The dynamic-import workaround from 6a0ac63 is
  no longer needed once the root tsconfig + TSX_TSCONFIG_PATH expose
  decorator metadata to tsx; verified by booting `pnpm dev` clean.
- server.ts: correct the inline structural type for `validateSession` to
  match the real `IAuthenticationService` contract (non-nullable, throws
  on invalid session) and wrap the call in try/catch so unauthenticated
  bubbles to a `null` return instead of dead-code `result ? ... : null`.
- bind-production.ts: extract `maybeRegisterRealtimePing()` that wraps the
  built-in ping inbound handler in the same `withSpan(withCapture(...))`
  sandwich the realtime-handler generator emits (R41–R44), so the
  proof-of-life channel models the convention rather than registering raw.
- bind-production.test.ts: add 4 tests for the `REALTIME_PING_DISABLED`
  env-gate (registered when unset in both binders, not registered when
  "true", treated as enabled when "1").
- docs/guides/realtime.md: correct the integration-test reference at
  line 285 — the test does not call `bindAllDevSeed()`; it builds the
  Socket.IO server inline and exercises gates 1+2 only (gates 3+4 live in
  socket-io-realtime-server.test.ts).
- adr-016: add a "Known follow-ups" section recording 6 lower-priority
  refinements deferred from this branch (bridge stub test scaffolding,
  registry register/registerChannel precedence, channel-template dot
  constraint, server bare catch{}, BindAllDeps Partial widening, AGENTS.md
  anchor count phrasing).

CI gates: lint 0 errors / 4 warnings (pre-existing turbo.json warnings),
typecheck clean, 24 web-next tests pass (was 20; 4 new env-gate tests),
boundaries 0 issues across 504 files.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 10:16:46 +02:00
6a0ac63bb9 fix(realtime): CI gate fixes surfaced by Phase 11 smoke tests
- no-direct-socket-io: extend allowlist to cover apps/*/src/**/*.test.ts so
  the realtime-ping e2e integration test can import socket.io/socket.io-client
  directly; add two valid test cases to keep the rule's own test suite green
- tsconfig.json (root): add root-level tsconfig with experimentalDecorators +
  emitDecoratorMetadata and no "include" so tsx 4.21.0's createFilesMatcher
  resolves decorator config for all workspace packages, not just web-next's
  own source tree
- web-next dev script: pass TSX_TSCONFIG_PATH=../../tsconfig.json so the
  custom Node server uses the root tsconfig for all modules it loads
- next.config.mjs: add @repo/core-events and @repo/core-realtime to
  transpilePackages so Next.js webpack can resolve their workspace source files
- server.ts: replace static authContainer import with a dynamic import inside
  IRealtimeAuthenticator.authenticate so Inversify decorators are applied only
  after bindAll() has already populated the container

All CI gates pass: lint (0 errors), typecheck, 20 tests (incl. realtime-ping
e2e), boundaries (0 issues).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-09 01:32:43 +02:00
b9caf605d2 test(web-next): e2e realtime-ping (4 checkpoints) 2026-05-09 00:39:44 +02:00
2351ca6249 feat(web-next): register realtime-ping inbound (env-gateable) 2026-05-08 23:20:58 +02:00
4032e5a722 feat(web-next): bindAll wires (realtime, realtimeRegistry) through every feature
Extends bindAll/bindAllProduction/bindAllDevSeed to accept BindAllDeps
and thread realtime + realtimeRegistry as the 6th and 7th positional args
into each per-feature binder. Adds bindRealtimeBridge stub (empty allowlist
in v1). bindAll accepts optional deps with InMemoryRealtimeBroadcaster
fallback so existing page-level callers stay type-safe.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 22:51:39 +02:00
5659a0f61b feat(web-next): custom Node server hosting Next.js + Socket.IO on port 3000
Replaces `next dev` / `next start` with a custom Node http server that
co-hosts Next.js and Socket.IO on the same port, wiring in the
RealtimeHandlerRegistry and session-cookie-based IRealtimeAuthenticator.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 22:51:27 +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
d800d98574 feat(web-next): bindAll resolves IEventBus + IJobQueue per env
resolveEventsAndJobsProduction wires PayloadJobsEventBus + PayloadJobQueue
against the bootstrapped Payload instance; resolveEventsAndJobsDevSeed
wires InMemoryEventBus + InMemoryJobQueue. Each per-feature binder now
receives (bus, queue) so Phase 7 generators can subscribe handlers and
register job tasks at the <gen:event-handlers>/<gen:jobs> anchors.
2026-05-08 16:09:57 +02:00
72d5513916 chore(tsconfig): migrate off deprecated baseUrl
TypeScript 6 deprecates `baseUrl` in favor of resolving `paths`
relative to the file that defines them. Earlier commit (bde40e4)
silenced the warning via `ignoreDeprecations`; this commit does
the actual migration so the warning goes away on its merits.

Changes:

1. tsconfig.base.json: drop `baseUrl: "."`. Add an explicit `./`
   prefix to every `paths` entry so they resolve relative to the
   base config's location (the repo root) — same behavior as
   before, but no baseUrl needed. (TypeScript requires path entries
   to be relative or absolute when baseUrl is absent; bare paths
   like "packages/..." are not allowed.)
2. apps/web-next/tsconfig.json: drop baseUrl. The `@/*` mapping's
   target was already "./src/*" — relative-from-tsconfig-file is
   the new default, so no other change.
3. apps/cms/tsconfig.json: same — drop baseUrl, paths already use
   "./" prefix.
4. apps/storybook/tsconfig.json: same.
5. apps/web-tanstack/tsconfig.json: same.

Generator templates (turbo/generators/templates/feature/tsconfig.json.hbs)
already omit baseUrl, so future-generated features inherit the new
posture.

Reverts the ignoreDeprecations setting added in bde40e4 — no longer
needed.

Verified:
- pnpm typecheck 14/14
- pnpm lint 15/15
- pnpm test 26/26

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 09:44:00 +02:00
e1b6ecf578 feat(web-tanstack): Sentry instrumentation via @sentry/node + @sentry/react + R38 PII test
Adds initSentryServerNode + initSentryClientReact to core-shared
(Vite/non-Next variants of the existing init helpers — same R31/R32/R33
posture, R34/R35/R37 replay defaults). Extends no-sentry.ts to mock
@sentry/node + @sentry/react. Wires the web-tanstack server/client
instrumentation entry hooks and adds the R38 PII test.

Spec deviation: web-tanstack has no vite.config.ts yet (placeholder app
per its package.json). The @sentry/vite-plugin dep is added but unused
until the TanStack Start build is wired in a later plan. A minimal
src/vite-env.d.ts shims ImportMetaEnv for the client entry until the
full Vite types land.

@sentry/node and @sentry/react are added to core-shared as optional
peerDependencies so feature packages don't transitively pull them in;
they're also devDependencies of core-shared for typecheck/test runs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 20:25:14 +02:00
d348cb9179 feat(cms): Sentry server instrumentation + withSentryConfig + R38 PII test
Adds apps/cms/instrumentation.ts (server-only — Payload admin client DSN
is out-of-scope per spec §8). Wraps the Payload-wrapped next config with
withSentryConfig. Adds the R38 PII scrubber test. Required adding
@repo/core-shared as a direct dep of cms (was only transitive before).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 20:14:56 +02:00
f911892d0b feat(web-next): Sentry instrumentation hooks + withSentryConfig + R38 PII test
Adds apps/web-next/instrumentation.ts (server) and instrumentation-client.ts
(browser) hooks, wraps next.config.mjs with withSentryConfig (R52), and adds
the R38 per-app PII scrubber smoke test.

Spec deviation: extend PII_KEY_SUBSTRINGS with "ipaddress" so keys like
ipAddress trigger key-level redaction (tighter posture than the spec's
substring list; existing scrub.test.ts still passes).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 20:13:39 +02:00
a943f95929 feat(media): wire instrumentation — media repo spans + getMedia/listMedia/deleteMedia withSpan
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 18:01:46 +02:00
e14a23dccd feat(navigation): wire instrumentation — header repo spans + getHeader withSpan
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 17:59:14 +02:00
404cb07e79 feat(marketing-pages): wire instrumentation — site-settings + pages spans + use-case/controller withSpan
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 00:26:45 +02:00
64ffb009e1 feat(auth): wire instrumentation — users repo spans + sign-in/up/out withSpan
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 00:24:20 +02:00
5903cef70a feat(blog): wire instrumentation — repo spans + use-case/controller withSpan + logger capture
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 00:18:13 +02:00
07e8b2e2e7 test(app): R47 — bindAll instrumentation orthogonality matrix
Extends bind-production.test.ts with a vi.mock for @repo/core-shared/instrumentation
that wraps bindSentryInstrumentation and bindNoopInstrumentation in vi.fn (so call
counts are observable while real implementations still run). Adds 4 orthogonality
tests covering: DSN absent + production env, DSN set + dev env, Sentry + dev seed,
Noop + production — verifying instrumentation choice is independent of repo mode.
Total: 6 original + 4 new = 10 passing tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 00:04:26 +02:00
efacb0e072 feat(app): bindAll() Rule 0 — DSN-driven instrumentation (orthogonal to repo mode)
Introduces resolveInstrumentation() in apps/web-next/src/server/bind-production.ts:
reads WEB_NEXT_SENTRY_DSN; if set, calls bindSentryInstrumentation; else Noop.
Both bindAllProduction and bindAllDevSeed call resolveInstrumentation() at the
top. Exports __resetBindStateForTests() and __getInstrumentationForTests() for
test helpers. Adds inversify + reflect-metadata as direct dependencies of web-next.
Existing 6 tests still pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 00:03:27 +02:00
8f34daca36 docs(dev-seed): canonical doc updates + refactor-log entry
- CLAUDE.md Key Conventions: 'App bootstrap' rule rewritten as 'Three
  binding modes per feature' — describes USE_DEV_SEED + NODE_ENV
  resolution order and the new ./di/bind-dev-seed export.
- AGENTS.md (root): exports list now mentions ./ui + ./di/bind-dev-seed;
  Per-feature public-API surface table gains a row; Apps section shows
  the bindAll() dispatcher with three-rule logic.
- docs/architecture/vertical-feature-spec.md §6: file shape now
  includes bind-dev-seed.ts, bind-dev-seed.test.ts, __seeds__/dev.ts;
  package.json exports list updated to include ./di/bind-dev-seed.
- docs/architecture/data-flow-explainer.html: anatomy tree gains
  __seeds__/ row; LAYERS.di description updated with new binders +
  cross-link to di-explainer.html; new LAYERS.seeds entry; public-
  surface card expanded to six subpaths.
- docs/superpowers/refactor-logs/2026-05-06-input-output-unification.md
  §7: new 'Post-Plan-9: dev-seed binders' entry summarizing the rollout
  (commits, per-feature additions, app wiring, tests, turbo, docs).
- bind-production.test.ts: dispatcher tests use vi.stubEnv (typesafe
  way to test process.env in TypeScript 5+ with @types/node read-only
  process.env types). 4 dispatcher tests + 2 bindAllProduction tests
  = 7 tests total.
2026-05-06 19:49:58 +02:00
6bf19f35c5 feat(app): bindAll() now checks NODE_ENV in addition to USE_DEV_SEED
Three-rule resolution order in bindAll() (first match wins):

  1. USE_DEV_SEED === 'true'   → bindAllDevSeed (explicit override)
  2. NODE_ENV    === 'production' → bindAllProduction
  3. otherwise                  → bindAllDevSeed (developer default)

Rationale: 'pnpm dev' should boot the app without requiring Payload to
be running locally — dev seed is the more useful default for non-
production environments. Production servers explicitly set
NODE_ENV=production and get the real binding. The USE_DEV_SEED override
remains the escape hatch (force seed in any NODE_ENV — e.g. staging
preview, design review).

bind-production.test.ts grows from 3 tests to 8 — covers the dispatcher
matrix:
- USE_DEV_SEED='true' wins even when NODE_ENV='production'
- NODE_ENV='production' (no override) → production
- NODE_ENV='development' → dev seed (default)
- NODE_ENV unset → dev seed (default)
- USE_DEV_SEED='false' treated as not-set (only the literal 'true' triggers)
- Pre-existing 'binds all five repos' test now also asserts bindProductionMedia

di-explainer.html conditions table + mode flag strings updated to match
the new three-rule logic.
2026-05-06 19:32:00 +02:00
68e934c0a5 feat(app): wire bindAll() + bindAllDevSeed() dispatcher; add DI explainer page
apps/web-next/src/server/bind-production.ts now exports three functions:
- bindAllProduction() — production-only binders
- bindAllDevSeed() — dev-seed-only binders (NEW, calls all 5 features)
- bindAll() — dispatcher that branches on USE_DEV_SEED env var

All page/route callers (page.tsx, about/page.tsx, blog/[slug]/page.tsx,
api/trpc/[trpc]/route.ts) updated from bindAllProduction → bindAll so the
env flag actually has effect.

docs/architecture/di-explainer.html (NEW): standalone interactive page
explaining the di/ folder file-by-file, the loading sequence (8 stages),
the three binding kinds (.to / .toDynamicValue / .toConstantValue), an
interactive three-mode picker showing how the same blogContainer state
differs across default/dev-seed/production, a conditions table, and a
final card on how tests bypass DI entirely. Sister page to
data-flow-explainer.html.

Refactor log entry + canonical doc updates follow in subsequent commits.
2026-05-06 19:10:29 +02:00
2df137c70c chore(plan-9): final verification + changelog summary
Straggler fixes: web-next and web-tanstack app callers did not pass {}
to queryOptions()/caller calls after Plan 9 added .input(z.object({}).strict())
to siteSettings and header procedures. All 360 tests pass, full typecheck
green across 14 packages. Refactor log §7 updated with verification summary.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 16:07:36 +02:00
8a36d803b3 feat(media): full Clean Architecture scaffold
Media is now a complete vertical-feature package mirroring auth/blog
structure: entities (models + errors), application (repositories +
use-cases), infrastructure (real Payload-backed + mock siblings),
interface-adapters (per-use-case controllers), DI (symbols + module +
container + bind-production), integrations/api (mediaRouter), factory,
contract suite, and feature integration tests.

Wired into:
- packages/core-api/src/root.ts (added `media: mediaRouter`)
- apps/web-next/src/server/bind-production.ts (calls bindProductionMedia)
- tsconfig.base.json (added @repo/media/api and ./di/bind-production aliases)

56 new tests in @repo/media (13 test files); core-api router test updated
to assert media. procedures. All 26 turbo tasks green.

Refactor log: §2, §4.1, §4.2, §5.1, §6.1
Spec: §6.5

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 00:29:05 +02:00
bd50a67662 feat(storybook): wire @storybook/test-runner for story smoke tests
Every story is now executed as a smoke test (mount + no console errors)
via @storybook/test-runner. New script: pnpm test:stories runs
build-storybook then test-storybook against the static build.

Spec: §6.8

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 19:10:41 +02:00
119eab49fe feat(apps): add unit tests for providers + bind-production + cms config
web-next: bindAllProduction calls all 4 feature binders exactly once;
Providers renders children. web-tanstack: equivalent providers + bind tests.
cms: payload.config exports a SanitizedConfig with all expected collections.

Spec: §6.7, §9

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 16:34:19 +02:00
eb55a698f3 fix(turbo-boundaries): resolve 32 violations
- Re-tag core-trpc as core-composition (transitively reaches features
  through core-api's AppRouter type) and allow core-composition packages
  to depend on other core-composition packages in turbo.json
- Add @payloadcms/richtext-lexical as direct dep of apps/cms (was pulled
  transitively via core-cms; Payload's importMap.js imports it directly)
- Add @storybook/react as devDep of core-ui and apps/storybook (stories
  belong with components per Atomic Design)
- Update apps/storybook .storybook/{main,preview}.ts to point at
  packages/core-ui (was still referencing deleted packages/ui) and export
  CSS via package exports instead of direct file import
- Add JSDoc type annotation to Payload-generated importMap.js to suppress
  TypeScript's TS2742 error from complex inferred types
- Add storybook-static to eslint ignores in core-eslint base config

pnpm turbo boundaries now reports zero violations.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 12:12:27 +02:00
9899e213ca build(turbo): add boundaries enforcement matching ESLint dependency graph
Per-package tags + root boundaries block now enforce the same three-tag
model as eslint-plugin-boundaries:
- app          → may depend on: app, core, core-composition, feature, tooling
- feature      → may depend on: core, tooling
- core         → may depend on: core, core-composition, tooling
- core-composition (core-api, core-cms) → may depend on: core, feature, tooling
- tooling (core-eslint, core-typescript) → may depend on: tooling

Tags applied: 4 apps (app), 3 core foundation packages (core),
2 core composition packages (core-composition), 5 features (feature),
2 tooling packages (tooling). All test suites pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 11:59:44 +02:00
0972645ebb refactor: rename eslint-config + typescript-config to core-eslint + core-typescript
Aligns tooling packages with the core-* naming convention used by all
other foundation packages (core-shared, core-cms, core-api, core-trpc,
core-ui). Updates ~50 files: package.json names, devDependencies,
tsconfig extends, eslint.config imports, vitest.config imports, AGENTS.md
references, and the boundaries plugin patterns to match the new paths.

The tooling-specific patterns in boundaries/elements are now ordered BEFORE
the broader core-* pattern to ensure correct first-match-wins behavior.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 10:37:07 +02:00
3856701252 fix(lint): exempt next-env.d.ts triple-slash + declare globalEnv vars
next-env.d.ts is a generated file using triple-slash references that
TypeScript requires. ESLint exemption added in apps/web-next config only.
Also declare CI, DATABASE_URL, PAYLOAD_SECRET, NODE_ENV in turbo.json
globalEnv so turbo/no-undeclared-env-vars stops warning.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 10:02:33 +02:00
2c6c836206 docs(agents): write per-app AGENTS.md for cms, web-next, web-tanstack, storybook 2026-05-05 10:00:28 +02:00
a7b9890db5 test(web-tanstack): add Playwright scaffold + skipped home spec 2026-05-05 09:26:19 +02:00
106e5c2737 test(web-next): add Playwright config + smoke specs (home, about, blog 404) 2026-05-05 09:25:42 +02:00
22bee5362f feat(eslint-config): add boundaries plugin enforcing app→feature→core graph
- Install eslint-plugin-boundaries@^4.2.2 to enforce three-tag boundary model
- Configure element types: app, core-composition (core-api/core-cms), core, feature, tooling
- Enforce unidirectional dependency graph: apps→features→core, core-composition→features
- Add eslint.config.js to all 17 packages and apps (required for ESLint 9 flat config)
- Fix pre-existing linting issues to achieve clean lint pass

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 09:21:01 +02:00
acae859773 chore: delete legacy packages (api, api-client, cms-client, cms-core, core, ui) 2026-05-05 09:13:08 +02:00