Demo · 8 September 2026

Fullstack Test Shop

Where things are in the code, how to run it and what was checked.
Version 767226bf3c2f · prepared on 8 September 2026

About the project

The assignment asked for a digital goods shop with catalog, checkout and payment. I extended the base scenario with an idempotent webhook inbox, concurrency-safe key fulfillment, stage retries and observable failure states.

The test assignment is implemented as a complete digital shop flow: Angular storefront, NestJS API, PostgreSQL via Prisma, payment webhook, two key providers and a background fulfillment worker. The UI covers purchase, repeated payment events and recovery after stock or provider failures.

What sets the implementation apart

Fulfillment happens once even under repeated or concurrent webhooks. A stable provider request ID survives an ambiguous timeout; out_of_stock and delivery_failed recover on a later worker pass. Database constraints and FOR UPDATE SKIP LOCKED enforce invariants at the storage layer.

Application-code composition

Angular / TypeScript 32%NestJS 30.4%Prisma / PostgreSQL 18.4%Node.js delivery worker 12.5%Node.js provider adapters 3.8%TypeScript contracts 2.9%

Shares use Git application-file bytes at pinned revisions. Each file belongs to one subsystem under scripts/generate-stack-share.mjs rules; tests, assets, dependencies and generated files are excluded. Rounded to 0.1%. This describes code composition, not proficiency.

  • Payments and providers are explicitly mocked; no money is charged and codes are for demonstration only.
  • Up to 20 orders per session and 1,000 new demo orders in total. One-hour TTL, cleanup every five minutes.
  • The recovery example deliberately fails the first delivery attempt for one order. It does not change global provider modes.

Screenshots, diagrams and source evidence retain their original language; captions and descriptions are translated.

Architecture and diagrams

  • Prices and discounts are calculated on the server and saved in the order.
  • A unique index protects Idempotency-Key; replayed input is checked against the original intent.
  • Webhooks are saved to a durable inbox first. A separate worker processes payments and the delivery queue.
  • The provider requestId remains stable across retries. An ambiguous timeout does not immediately allow a second code to be issued.
Components of the published demo
Components of the published demo · Mermaid ↓
Main workflow
Main workflow · Mermaid ↓
Deployment of the published version
Deployment of the published version · Mermaid ↓
Data structure and storage boundaries
Data structure and storage boundaries · Mermaid ↓

Code map: files and dependencies

This map is tied to version 767226bf3c2f. The table lists the screen or API, related module and data.

FeatureScreen / APIModuleData / verification
PurchaseStorefront / POST ordersstorefront.component; ShopService.createOrderorders, products, promocodes; race tests
PaymentPOST payments/simulate → webhooks/paymentPaymentsController; acceptWebhookpayment_events; duplicate event_id
DeliveryOrder / GET orders/:idworker.service processDeliveryJobdelivery_jobs, provider_requests, fulfillments; recovery
SessionGuard for all public ordersportfolio-demo PortfolioGuardHMAC cookie, prefix owner; tests/portfolio/run.ts
Reset / TTLPOST demo/reset / timerPortfolioCleanup.clearportfolio orders only; ownership / expiry tests

Using the code map

  1. Before making a change, find the feature and trace its links to the API, state and storage.
  2. Check inputs, errors, repeated events and dependent workflows.
  3. After making a change, update the map and affected diagrams alongside the code.
  4. Run the related checks and link the new evidence to the source version.

Workflows and API

  1. Choose a product and complete a successful test payment. Wait for the code and inspect the history.
  2. Replay the same payment event: the code and delivery must remain unique.
  3. Create an order using the failure scenario, pay and select “Recover my order”.
  4. Check a declined payment, another session's UUID and resetting your own example.

Verification of the published version

CI: CI ↗ · 767226bf · this demo's version · 2026-09-07T00:49:05Z

CI: Portfolio immutable image ↗ · 767226bf · this demo's version · 2026-09-07T00:49:05Z

  • Real HTTP webhook, durable inbox, worker, single fulfillment preserved on event replay
  • Foreign GET/recover return 404; other session reset preserves first order
  • Payment failure; isolated first-attempt delivery fault; own recovery succeeds

These checks apply to the listed version. Business metrics and model quality on an independent dataset were not measured.

Measurements

Total project container resources · 2026-09-07T01:08:27 — 01:11:22 UTC
Total project container resources · 2026-09-07T01:08:27 — 01:11:22 UTC · Source data ↓
Measured scenario repetitions over HTTPS · 2026-09-07T01:08:36 UTC; methodology limitations in JSON
Measured scenario repetitions over HTTPS · 2026-09-07T01:08:36 UTC; methodology limitations in JSON · Source data ↓
  • 14 meaningful screenshots of the actual interface retained.
  • Each screenshot includes its date, scenario and code revision.
  • Peak container RAM in the short test: 218.56 MiB. Shared services are counted separately; the shop includes its own database.
  • 6 scenario repetitions measured; median 129.0 ms, maximum 1939 ms. Timing includes the browser and HTTPS; methodology and limitations are included.

Running and operating

The demo and original app use the same order model. PORTFOLIO_DEMO=true enables the demo guard. Without the flag, the original API contracts apply.

GitHub Actions builds a pinned commit SHA. A prebuilt GHCR image is uploaded to the VPS. The shop database remains separate from the new applications.

Start: docker compose --env-file .env.production -f compose.production.yaml up -d. Run prisma migrate deploy before switching releases. Secrets are stored only on the server. Do not use seed as an unconditional reset of a running shop.

Readiness: /api/health/ready checks PostgreSQL. During an incident, compare the order history, inbox and delivery job; retry delivery for the original orderId instead of creating another purchase.

Builds run outside the VPS; the server receives static files and versioned images. Secrets are kept separately. Logs rotate; changing log options requires recreating the container. No server-wide docker prune.

The code map links a screen or API to its module and data. A change needs those links checked, the map updated and the affected flows rerun: normal path, error, retry and reset. Diagrams can go stale, so their version is listed alongside them.

Rollback checked at 2026-09-07T01:07:46.255650+00:00: 20260907-verified → 20260907 → 20260907-verified. HTTPS, readiness and SHA were confirmed after each switch. This checks configuration and artifacts at one verified SHA; no reverse database migration was performed.

Stack

Angular / TypeScriptStorefront, state signals, HTTP client and order polling.
NestJSContracts, validation, webhooks, recovery operations and demo limits.
PostgreSQL / PrismaMonetary snapshots, inbox, leased queue, unique indexes and transactions.
Node.js workerProvider HTTP calls outside short transactions, retries and final delivery.

Materials and source code

Implementation history: 1–3 September 2026. Portfolio preparation: 7 September 2026.

The evidence archive retains its original language.