Conversation
Adds the approved Claude Code pipeline design spec, the 9-phase roadmap with blocking-gate status rules, spec and phase-checklist templates, and the seeded Phase 00 checklist. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds the five spec-driven workflow skills (create-spec, plan-phase, implement-phase, verify-phase, project-status), six subagents (five stack specialists plus a read-only code reviewer), four enforcement hooks (post-edit formatting, secrets protection, Conventional Commits validation, session phase context), and documents the workflow in CLAUDE.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Bilingual (en-US / pt-BR) record of how the Claude Code build pipeline was planned: the plan-mode + brainstorming method, the five design decisions with options and rationale, and supporting decisions made during implementation. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
GET /admin/orders (paginated, filterable by status) and GET /admin/orders/:id let an ADMIN review any customer's orders -- gated by JwtAuthGuard + RolesGuard, unscoped by userId (same precedent as Phase 6's findById). Adds AdminOrderOutput/AdminOrderSummaryOutput (existing shapes plus userId/userEmail) without touching the customer-facing OrderOutput/ OrderSummaryOutput. Order status stays read-only here -- it remains driven exclusively by Phase 6's event consumer. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
InventoryClient port + HttpInventoryClient adapter call apps/inventory's existing internal stock endpoints over fetch, authenticated with the shared INTERNAL_API_KEY -- apps/api is the sole trusted caller, per the project's frontends-talk-only-to-NestJS rule. GET/PATCH /admin/inventory/:productId are ADMIN-gated and validate productId as a UUID before ever reaching the network call, so a malformed id 400s locally instead of surfacing as a misleading 502 from the proxy. A genuine inventory outage or unexpected response is a thrown BadGatewayException, never silently swallowed. Also enables CORS in main.ts (CORS_ORIGINS allow-list, disabled by default) -- closes a pre-existing gap against the project's own security rules, needed for the first time by the admin SPA's local dev server calling apps/api directly. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Proves GET /admin/orders (+:id) is a genuine cross-customer, ADMIN-only view (401/403/200, status filter, invalid-status 400, unscoped detail lookup, 404) and GET/PATCH /admin/inventory/:productId correctly proxies stock (401/403/200, update round-trip, negative- quantity 400, malformed-id 400, unseeded-id 404) via a new FakeInventoryClient test double, since apps/inventory has no host port reachable from the Jest process. createTestApp() gains an optional provider-override parameter, purely additive to every existing call site. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds a flat eslint.config.mjs (angular-eslint recommended + template rules, plus this repo's Prettier integration) and a lint script, matching apps/web's/apps/api's tooling conventions. Adds @angular/material + @angular/cdk with a subdued azure/blue Material 3 theme (deliberately not a loud demo palette, for an internal admin tool), animations wired via provideAnimationsAsync(). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
AuthService (signal-based state, in-memory access token, refresh token in localStorage with a documented accepted-risk rationale), a functional auth interceptor (attaches Authorization, retries once on 401 via silent refresh, propagates the original error if refresh fails), an ADMIN-only route guard, and a typed ApiClient wrapping HttpClient. Role is learned via GET /users/me after login/refresh, since neither endpoint returns it directly. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
AppShell (toolbar + sidenav nav, logout) is a routed layout component wrapping every authenticated route behind adminGuard in one place; /login stays outside it with no chrome. Adds reusable ConfirmDialog (+ ConfirmDialogService) and a generic paginated DataTable for the products/categories/orders list screens built in later tasks. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Material reactive-form login at /login. A CUSTOMER login still succeeds at the HTTP level (the API authenticates any valid credentials regardless of role), so the page checks isAdmin() after AuthService.login() resolves: ADMIN navigates to the dashboard, anyone else is immediately logged back out with a visible rejection message, never reaching an admin screen. Replaces the routing skeleton's throwaway LoginPagePlaceholder. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
DashboardPage (routed at the shell's index path) fires six parallel limit=1 list calls and reads only meta.total from each -- total products, total categories, total orders, and a breakdown by the three OrderStatus values -- with no new backend aggregation endpoint. Handles loading and error (with retry) states. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
ProductsService wraps product CRUD, category listing, and the stock proxy. ProductListPage: paginated/searchable table with a per-row stock column (tolerating a missing stock row), soft-delete behind a confirm dialog. ProductFormPage: shared create/edit form (dollar price converted to/from integer cents), a category dropdown, and an independent stock-correction action separate from the main save, with a visible error on a duplicate-slug 409. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
CategoriesService wraps list/create/update/delete; no getById since apps/api exposes no single-category endpoint -- the edit form reuses the already-fetched list instead. CategoryListPage/CategoryFormPage mirror the products feature's structure. A delete 409 (category still has products) and a save conflict both surface the API's own error message verbatim via a snackbar, per the spec's explicit requirement not to swallow that case. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
OrdersService wraps GET /admin/orders (+:id). OrderListPage: paginated table with a status filter (All/PLACED/PAID/PAYMENT_FAILED) and subdued status chips, row click to detail. OrderDetailPage: full order with line items, a clear "not found" state for a 404. No edit/delete/status -change control exists anywhere in this feature -- status stays exclusively controlled by the Phase 6 event-driven backend flow. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Replaces the Phase-1 placeholder README with the real feature set: routes, the SPA session model (in-memory access token, localStorage refresh token, accepted-risk rationale), and the core/shared/features layout. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
All checklist tasks complete, code review found no blockers, and every verification command passes: api and admin build/lint/unit tests, the full api e2e suite (admin-orders cross-customer listing/ filtering/RBAC, inventory-proxy round-trip via test double), both Docker images build, the full compose stack is healthy with the rebuilt images and no new host port, the admin SPA is served through the reverse proxy, and unauthenticated admin-orders access is rejected with 401. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Closes the remaining gaps from Phases 0-7 rather than adding new product features: a Playwright suite for apps/admin, an EVENT_PUBLISHER_MODE toggle (default fake, unchanged automated behavior) to opt into the real QStash/HTTP adapters already built, a manual guide for the real end-to-end event flow (requires a live Upstash account this repo has no access to), a GitHub Actions CI workflow, correlation-id propagation on apps/inventory's/apps/payment's plain REST routes, and Fly.io deployment configuration plus a manual deploy guide. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds the env var apps/api's, apps/inventory's, and apps/payment's upcoming mode-selectable EventPublisher wiring needs -- defaults to fake everywhere, so compose behavior is unchanged until each service gains the conditional wiring itself. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
newEventPublisher selects the real QStash adapter only when EVENT_PUBLISHER_MODE is exactly "real", defaulting to the in-memory fake for any other value. The plain GET/PATCH stock routes gain a WithCorrelationID middleware (reads X-Correlation-Id, generates one via crypto/rand if absent, echoes it back) whose value is now included in every log line for those routes -- the QStash webhook route is left untouched since it already sources a correlation id from the event envelope. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
eventPublisher() selects QStashEventPublisher only when event.publisher.mode (mapped from EVENT_PUBLISHER_MODE) is exactly "real", defaulting to InMemoryEventPublisher for any other value. A new CorrelationIdFilter reads/generates an X-Correlation-Id per request, threads it through SLF4J MDC (cleared afterward to avoid leaking across pooled threads) so it appears in every log line, and echoes it on the response -- harmless on the QStash webhook route, which sources its own correlation id from the event envelope and never reads this filter's MDC entry. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
selectEventPublisher() picks QStashEventPublisher only when EVENT_PUBLISHER_MODE is exactly "real", defaulting to FakeEventPublisher otherwise -- wired into EventsModule's useFactory. InventoryClient's getStock/setStock now take a correlationId, threaded explicitly from InventoryController's request (no request-scoped DI exists anywhere in this codebase, so this matches its existing explicit-parameter style) through the use cases and into HttpInventoryClient's outbound X-Correlation-Id header -- matching the literal header apps/inventory's own correlation-id middleware reads. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
A single job runs the exact command every phase's own README/checklist
already documents at the root ("pnpm turbo run build lint test"),
which drives every app uniformly -- apps/inventory and apps/payment
included, via their existing thin package.json wrappers. Triggered on
push/PR to main/master. Does not run any docker-compose-backed e2e
suite, per this phase's spec.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
One fly.toml per deployable app, mirroring the compose topology's access rules: apps/web, apps/admin, apps/api get a public HTTPS route; apps/inventory and apps/payment declare no public service at all, reachable only via Fly's private networking from apps/api -- enforcing the "frontends/public internet never reach Go or Spring Boot directly" rule at the deployment-topology level, not just the reverse-proxy level. docs/deployment/fly-io.md walks through Postgres provisioning (one cluster backing all three logical databases, same as the compose container), secrets per app, and the deploy sequence. This is a documented, user-run deployment -- no live Fly.io account is available here to execute or verify it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Walks through a real Upstash QStash account, temporarily exposing apps/inventory's and apps/payment's webhooks via ngrok (their host ports stay unpublished otherwise), setting EVENT_PUBLISHER_MODE=real, and placing a real order to observe the same order.created -> stock decrement -> payment processed -> order status updated flow every automated test already proves with fakes -- now genuinely asynchronous through a real message broker. Manual and non-blocking, since no live Upstash account is available here to execute or verify it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
apps/admin/test-results/ (traces, error-context.md, .last-run.json) got committed alongside the new e2e suite; untrack it and ignore it going forward, mirroring apps/web's existing test-results/playwright- report/playwright/.cache/ patterns. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Root README: CI badge, a Testing section covering every app's suite (including the new admin Playwright suite and the manual real-event- flow guide), a Deployment section linking the Fly.io guide, drops stale "future Fly.io deployment" framing now that real config exists. apps/inventory, apps/payment: document the new inbound X-Correlation-Id handling on their plain REST routes and the EVENT_PUBLISHER_MODE toggle, replacing stale "fake is hardcoded" language. apps/api: documents the Phase 7 admin endpoints (GET /admin/orders, GET/PATCH /admin/inventory/:productId) and their env vars (CORS_ORIGINS, INVENTORY_BASE_URL, INVENTORY_INTERNAL_API_KEY), which had never been added to this README, plus EVENT_PUBLISHER_MODE. apps/admin: documents the new Playwright e2e suite. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
All checklist tasks complete, code review found no defects, and every verification command passes: api and admin build/lint/unit tests, the existing api e2e suite unmodified (proving EVENT_PUBLISHER_MODE defaulting to fake changed nothing), the new admin Playwright suite (6/6, including a real stock round-trip through apps/inventory), apps/inventory's and apps/payment's Go/Java suites (including new mode-selection and correlation-id tests), a valid CI workflow, a fly.toml for every app with inventory/payment correctly declaring no public route, complete deployment/manual-verification docs, and a fully healthy compose stack built and torn down cleanly with every service defaulting to EVENT_PUBLISHER_MODE=fake. This closes the roadmap: all 9 phases (0-8) are now Done. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Finish the README bilingual pass started in 7648d61: translate apps/api/test, apps/inventory, apps/payment, and apps/web READMEs to PT-BR-then-EN-US, and add new bilingual READMEs for packages/config, packages/shared, packages/types, and packages/ui, which previously had none. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.