# go-cart-actor — agents map The **commercial heart** of the platform. Orleans-style grain actors for cart, checkout, order, profile, inventory, plus a **UCP (Universal Commerce Protocol) HTTP adapter** at `internal/ucp/`. Deploys multiple binaries in parallel (one per concern) coordinated via k8s and an internal actor discovery/RPC layer. See `docs/checkout-order-handoff.md` for the role split with `go-order-manager`. ## Where to start - `cmd/cart/main.go` — the one most commonly run in dev. - `pkg/actor/` — the grain framework (start with `grain.go`, then `simple_grain_pool.go` and `grain_pool.go`). - `pkg/cart/cart-grain.go` — a concrete grain, the cleanest example. - `internal/ucp/handler.go` and `ucp/{cart,checkout,order,profile}.go` — the protocol adapter over the grains. - `go-cart-actor/README.md`, `TODO.md`, `NEW_MUTATIONS_SPEC.md` — current intent and known gaps. ## Architecture - **Grain model**: each domain entity (cart, order, checkout…) is a grain keyed by an opaque ID. Per-aggregate state machine lives in the grain's `state.go`; mutations are individual `mutation_*.go` files under `pkg//` and registered through `mutation_registry.go`. - **RPC**: gRPC over [`proto/`](proto/) — `cart.proto`, `checkout.proto`, `order.proto`, `profile.proto`, `control_plane.proto`. Pod discovery via `pkg/discovery/` + `pkg/proxy/remotehost.go` (k8s host discovery in `cmd//k8s-host-discovery.go`). - **Binaries** (`cmd/`): - `cart/`, `checkout/`, `order/`, `profile/`, `inventory/` — one each. - `backoffice/` — the admin UI host, plugged into `backoffice` via `pkg/backofficeadmin/`. - `ucp-artifacts/` — emits the protocol artefacts (signing, handler bindings). - **UCP**: `internal/ucp/` is the protocol adapter — it talks to the grains via RPC, not directly. Separate from `pkg/{cart,checkout,…}`. - **Cross-cutting**: `pkg/outbox/`, `pkg/idempotency/`, `pkg/flow/`, `pkg/promotions/`, `pkg/voucher/`, `pkg/telemetry/`. - **Auth**: `internal/customerauth/` — password hashing (`password.go`), rate limit, mail notifier, redis store, opaque customer session tokens. ## Important files by area | Area | File(s) | | -------------------------- | ------------------------------------------------------ | | Grain framework | `pkg/actor/{grain,grain_pool,simple_grain_pool,state,disk_storage}.go` | | Grain RPC | `pkg/actor/{grpc_server,grpc_server_test}.go` | | Cart mutations | `pkg/cart/mutation_*.go` (+ `cart-grain.go`) | | Order mutations | `pkg/order/mutation_*.go` + `pkg/order/order-grain.go` | | Order outbox / payment | `pkg/order/{emit_created,payment,stripe,klarna}_*.go` | | Promotions / vouchers | `pkg/promotions/`, `pkg/voucher/` | | Idempotency | `pkg/idempotency/store.go` | | Outbox (event publish) | `pkg/outbox/outbox.go` | | UCP protocol adapter | `internal/ucp/{handler,cart,checkout,order,customer,profile}.go`, `signing.go` | | Backoffice admin | `pkg/backofficeadmin/{app,hub,fileserver,customer}.go` | | Customer auth | `internal/customerauth/{server,redis,password,tokens,mail_notifier,ratelimit}.go` | | Telemetry / OTel | `pkg/telemetry/{otel,logs}.go` | | k8s service discovery | `pkg/discovery/discovery.go`, `pkg/proxy/remotehost.go`, `cmd//k8s-host-discovery.go` | | Tests integration scaffold | `cmd/cart/projection_*_test.go`, `pkg/promotions/apply_test.go` | ## Cross-project seams - **`platform/`**: uses `platform/auth`, `platform/catalog`, `platform/event`, `platform/inventory`, `platform/order`, `platform/tax`, `platform/rabbit`. - **`go-order-manager`**: subscribes to order events off the RabbitMQ topology (`docs/checkout-order-handoff.md`). - **`go-shipping`**: pulled via HTTP from `cart` (the cart client). - **`slask-tracking`**: independent consumer of order events for analytics. - **`backoffice`** (commerce tag): exposes the `pkg/backofficeadmin/` host. ## Improvement suggestions - **Mutation file explosion**: each behavior of a grain lives in its own `mutation_*.go`. This is shallow — the deletion test says removing one just moves the same code to its sibling file. Consider grouping related mutations per feature slice (e.g. one `cart_subscription.go` for add/remove/upsert subscriptiondetails), so the test surface and locality live together. - **`pkg/cart` vs `internal/ucp` vs `pkg/checkout`** — three layers touch the same conceptual "cart" entity. The UCP adapter depends on the grain, the grain depends on the protocol-specific mutations, and the checkout layer brokers a different view of the cart. Drop the conceptual split here: consider promoting one domain (`cart`) as the seam and treating the others as adapters. - **Inconsistent layout**: most binaries are at `cmd//main.go`, but `internal/ucp/`, `internal/customerauth/`, and `pkg/voucher/`, `pkg/outbox/` sit at different depths. A short module-layout doc would prevent the next contributor from guessing where new helpers go. - **`TODO.md` and `NEW_MUTATIONS_SPEC.md` live in the repo root.** Both belong in `docs/` so the README is the only thing newcomers hit first. - **Two proto variants**: `proto/checkout.proto` and `proto/checkout/checkout.proto`. Likely a historical artefact (see `proto/README` if it exists, otherwise grep `proto/` for `checkout` to see which is actually imported). - **Test coverage is uneven across `pkg/*`** — vendor-friendly modules like `pkg/promotions/` have `_test.go`, others like `pkg/voucher/` rely on `parser_test.go` only. Worth a pass to seed unit tests at each public function entry. - **`cookies.txt` at repo root** is not a build artefact and shouldn't be committed.