feat(e2e-ui): local workbench cluster gitops + SecretStack vault - #176
feat(e2e-ui): local workbench cluster gitops + SecretStack vault#176patrickleet wants to merge 342 commits into
Conversation
Teach-first home and cleaned UI across todos/chat/session/admin/blob. Todo/chat use public #[event] command methods; handlers stay thin. Blob moves to [[gameId]] with local board paint so New game updates immediately while history still uses the shared cache.
Optimistic level-complete painted the board before the finishing move committed, so start_level loaded an incomplete aggregate and rejected. Gate Next level on server-confirmed completion and await the move drain.
The #[event]+when= domain polish changed todo.completed/reopened/archived payloads (empty → owner_id) and renamed (title → owner_id,title). Existing streams failed hydrate, so load/command paths looked like nothing saved. Restore Result + record_* command/event pairs with the original payloads; handlers match again. Chat restored for the same hard-error pattern.
Show only copy + Start game when no game is selected, so the empty state does not look like a broken half-rendered grid.
Chromium flows against the live Fieldnote UI: OIDC Login V2 as alice/admin, todos lifecycle, chat post, blob start/move, session, unauth redirects, and role-gated admin. Run with make up + make run, then make test-browser.
Add integration-e2e-ui workflow (make test + Docker stack + browser e2e) and wire it into on-pr-quality and on-push-main so Fieldnote fixture regressions gate merges and releases.
Disable public HTTP command wildcards (T0 404) while mounting Zitadel
ingress/scrape explicitly. Include shadow/through tables in GraphQL
surface so m2m relationship predicates appear on bool_exp. Survive
blob /blob → /blob/{id} remount via remembered rows and list-seed merge.
Wait for client hydration before Start/New game, paint from mutation payload without remount-racing goto, and assert blob_games_start over the network in Playwright. Update api-contract tests for the current home story and generated command policies re-export.
Implements [[tasks/distributed-js-client-1]]
Implements [[tasks/graphql-qs-client-replica-2]]
Implements tasks/graphql-qs-client-replica-4.
Implements [[tasks/graphql-qs-client-replica-5]]
Implements tasks/graphql-qs-client-replica-15.
Implements [[tasks/graphql-qs-client-replica-6]]
Implements the server and compiler slice of [[tasks/graphql-qs-client-replica-10]].
Covers [[tasks/graphql-qs-client-replica-10]].
Generate role-scoped query and command artifacts from Rust Surface IR, make the normalized causal replica the only public client runtime, and migrate the SvelteKit e2e consumer to the generated contract. BREAKING CHANGE: remove the pre-release document cache, manual target/reconcile APIs, raw GraphQL command catalog, and pilot persistence format.
Implements [[tasks/graphql-qs-client-replica-18]]
Walkthrough panels now paste actual handler, domain, projection, RBAC, and generated-client snippets from the fixture instead of comment stubs.
Frame the site as the framework homepage — full-stack CQRS pitch, pillars, domain→service→client flow, compact playground cards, and local run. Demos stay destinations; ops/hosting only noted as roadmap.
Drop Meteor comparisons. Pitch Distributed as the next step after live GraphQL/query engines: keep the realtime client feel, add event-sourced commands, projections, OIDC surfaces, and generated TS clients.
Position Distributed around event-sourced commands, projections, and an honest client replica. GraphQL and SvelteKit are how the playground speaks, not the product definition.
Rename header/footer e2e-ui → distributed. Hero states Distributed as a cloud-native Rust and TypeScript framework for simple realtime, performant, scalable apps on distributed-systems foundations.
Rebuild home Features as the owner product story (two models, event-sourced aggregates, SQL+RBAC, inferred query edge, projections, browser replica, SvelteKit @load/@LiVe, OIDC) with playground code samples and syntax highlighting matching How-it's-built panels.
Public event→mutation authoring is now projection! (and compile_projection / ProjectionHandler). Matches CQRS product language and ProjectionDescriptor. Call sites use distributed::projection! so the macro does not clash with the projection module path. Legacy absence tests now assert the declarative macro is public while the old event-owning proc-macro stays gone.
Replace apply/as and on_deleted with multi-arm on blocks that bind event body or aggregate_id into mutation inputs. Align todos/chat/blob, home Features (mutation IR + lifetime highlighting), and demos with the new surface. Drop mutation_projector and on_state authoring.
Prefer query = Op.use() over list, and todos/games/pageMessages over generic rows, in app pages, home samples, and How-it's-built demos.
Expand the product home with a Brunson-style arc: claim band, backend/Rust/frontend SOTA as general industry bar (not product hooks), handoff to Distributed, then backstory and how it delivers. Teach unidirectional + event-driven as one path; tighten CAP wording; claim/band styles on home.css.
Expand How-it's-built overlays with ReadModel structs, aggregate shapes, domain event samples, and projection GraphQL mutations. Replace the home system-flow monospace list with a full-width circular dotted diagram.
Show Todos and Blob in nav for guests; requireAuth on page loads so client-side navigation redirects to /login?callbackUrl=… and returns after sign-in. Remove the standalone /public demo (lobby chat already covers anonymous). Honor callbackUrl on login/signup when already signed in; hero copy mentions realtime applications.
Ship one mutation IR with two proofs: Eventual (async projector + delta/expects) and Atomic (handler row + records). Rename wire/protocol states and APIs from causal/projected to eventual/atomic with no aliases. Direct placements export .applies previews for client optimism while still sealing from the atomic response. Command ledger migrations use atomic state (0004 + CHECK updates). Fix chat list optimism regressions: belongs_to joins are GraphQL/client nullable so missing author edges materialize, and full first-page offset indexes accept local optimistic inserts (re-sort + truncate). Regenerate e2e-ui clients, demos/docs, and JS tests for the new contract.
Add a shared hold-mutation helper and optimism.user.spec that requires chat post (including full first page), todos create/complete, and blob move continuity to paint before a delayed GraphQL response. Offline optimism-artifacts.test.mjs locks preview IR, atomic directProjection, nullable ChatMessages.author, and local first-page insert policy so gen/compiler regressions fail without a browser. Todos create under the delayed-route order test now asserts list paint before the wire returns.
Wire blob.move like todos/chat: command input carries the optimistic board outcome (map_json, score, status, …) and state_preview maps those fields into the client optimistic layer. A pure TypeScript twin of blob_domain::simulate_move fills the input; the handler still recomputes authority from game_id + direction only. Regenerate clients (full upsert preview), unit-test simulate_move parity, and require paint-before-wire on the player cell in optimism.user.spec.
No back-compat renames. Call sites and docs use .applies. Wire vocabulary test expects eventual/atomic only (rejects causal/projected).
Capture the accepted DX direction: same packages re-cut as monolith or microservices; Eventual projectors may split; Atomic seals stay collocated. Runtime pairs persistence, locks, and bus; process role selects outbox, consumer, and GraphQL. Implementation order and e2e-ui collapse targets included. Linked from usage skill and e2e-ui README.
Update generated-commands fixture, dctl client_compiler/cli_manifest expectations, GraphQL protocol tests, and e2e-ui behavioral suite to the eventual/atomic wire vocabulary (no causal/projected aliases).
Preserve applied migration history, register migration 4, complete the Eventual/Atomic rename, refresh generated contracts, and repair the affected e2e behavior. Resolves [[pr-170-eventual-atomic-rename-and-migration-failur]]
Add Helm deploy charts for api/ui with cluster-dev vs package posture, local PSQLCluster for the API, and hops.local Application YAMLs under gitops/env/local. Document hops local up as Option A for dogfood. Implements [[tasks/lwb-e2e-ui-gitops-charts]] [[tasks/lwb-docs-happy-path]]
When sourceDelivery.mode=sync, wait for .hops-synced / package manifest before cargo/vite so tar/mutagen can populate emptyDir first.
api deliveryPath points at e2e-ui Cargo root; ui at ui/ with vite. cluster-dev waits indefinitely for .hops-synced/package/Cargo before start.
…ault Add gitops/cluster tree (packages, providers, AuthStack, PSQLStack, e2e-identity MRs) and SecretStack vault backend claim for local workbench. Wire app charts/env Applications for cluster-dev delivery. Keep secrets out of YAML; document kubectl bootstrap in SECRETS.md.
|
Important Review skippedToo many files! This PR contains 922 files, which is 822 over the limit of 100. To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch. Upgrade to a paid plan to raise the limit. Usage-priced reviews support at most 300 files. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (29)
📒 Files selected for processing (922)
You can disable this status message by setting the Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Superseded by #177 (stacked on |
|
Closing in favor of #177 on the GraphQL QS epic stack. |
Summary
tests/e2e-ui/gitops/cluster/fixture: packages, providers/PCs, AuthStack, PSQLStack, e2e-identitysecrets/stack.yaml(backend: vault, optional Vault helm) — not metalocal/How to run
Test plan