Skip to content

Dev 01 - #1

Merged
gutomelo merged 170 commits into
masterfrom
dev-01
Jul 16, 2026
Merged

gutomelo merged 170 commits into
masterfrom
dev-01

Conversation

@gutomelo

Copy link
Copy Markdown
Owner

No description provided.

GmSoftware and others added 30 commits July 10, 2026 19:26
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>
GmSoftware and others added 29 commits July 15, 2026 10:55
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>
@gutomelo
gutomelo merged commit 4f772d7 into master Jul 16, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant