Dual web interfaces (app/frontend/)¶
app/frontend/ implements the two browser interfaces served by FastAPI using
HTML templates, JavaScript modules, Tailwind CSS, and Cytoscape.js:
- UI 1 (
TheLook Shopping Mall and Chat App,/shop): Mockupthelook_ecommerceshopping mall and customer support chat application (shopping_mall_url). - UI 2 (
Data Engineer Investigation Console,/console): Data engineer observability and graph investigation console (data_engineer_console_url).
Directory layout¶
The app/frontend/ directory contains the HTML templates and client-side
JavaScript controllers:
app/frontend/
├── README.md # UI 1 and UI 2 component specification (this file)
├── shop.html # UI 1: Mockup thelook_ecommerce storefront and ADK 2.0 chat widget
├── console.html # UI 2: Data engineer trace feed, Cytoscape.js graph, GQL workbench, and modals
└── static/
├── shop.js # Client controller for persona switching, orders, and refund chat
├── console.js # Client controller for Cytoscape.js rendering, 3-tab GQL runner, and modals
└── products/ # 8 locally hosted unbranded AI-generated studio product photos (256x256 PNG)
├── jacket.png
├── pullover.png
├── shoes.png
├── jeans.png
├── sunglasses.png
├── shirt.png
├── blazer.png
└── beanie.png
UI 1: TheLook Shopping Mall and Chat App (/shop)¶
UI 1 (TheLook Shopping Mall and Chat App, shopping_mall_url) simulates
an e-commerce storefront backed by the thelook_ecommerce operational schema in
Cloud Spanner (using Light theme as the fixed default):
- TheLook product catalog and warehouse view: Displays products, locally
hosted unbranded AI-generated studio product thumbnails (
getProductPhotoUrlmapping to/static/products/{jacket,pullover,shoes,jeans,sunglasses,shirt,blazer,beanie}.pngfor clean license management), brands, departments, retail prices, and fulfillment distribution centers hydrated fromthelook_ecommerce(GET /api/products). - Persona switcher: Allows students to switch between three pre-populated
customer profiles (
GET /api/customers), displaying each customer's loyalty tier badge (STANDARDvs.VIP) and 100-day return counter:- Customer A (
user_id: 1001,alice.chen@example.com,STANDARDtier): Customer with 2 prior returned items (status = 'Returned') in the last 100 days (limit: 10), an eligible delivered order (order_id: 90124, Alpine Gore-Tex Waterproof Shell Jacket,$129.00,status = 'Complete', delivered 14 days ago), and two edge-case orders (order_id: 90125, Polarized Aviator Titanium Sunglasses,$165.00, delivered 45 days ago andorder_id: 90126, Cashmere Ribbed Winter Beanie,$58.00in'Shipped'status). - Customer B (
user_id: 2048,jordan.taylor@example.com,STANDARDtier): Customer with 12 prior returned items (status = 'Returned') across distinct orders in the last 100 days (exceeding theSTANDARDlimit of 10) and a recent delivered order (order_id: 90588, CloudStride Trail Running Shoes,$148.00,status = 'Complete', delivered 10 days ago). - Customer C (
user_id: 3072,claire.vance@example.com,VIPtier): VIP customer with 12 prior returned items (status = 'Returned') in the last 100 days (within theVIPlimit of 20) and a recent delivered order (order_id: 90910, Tailored Italian Wool Travel Blazer,$210.00,status = 'Complete', delivered 7 days ago).
- Customer A (
- Bilingual UI toggle (
EN/한국어) with automatic demo reset: Both UI 1 (/shop) and UI 2 (/console) include a language toggle button (#lang-toggle-btn, persisted vialocalStorage.getItem('soa_ui_lang')) in the top navigation bar. Clicking the language button opens#reset-progress-modalwith a bilingual confirmation notice informing the user that switching languages resets the demo dataset (POST /api/demo/reset) and clears persisted chat/trace history (soa_chat_history_by_user,soa_pending_order_by_user, andsoa_active_user_id) so all orders, timestamps, prompt chips, and BigQuerysoa_action_lineagetraces start cleanly in the selected language. - Order history and two-step animated demo reset modal: Displays the selected
customer's
thelookorders, locally hosted product thumbnails, inventory item IDs, sale prices, delivery timestamps, and live statuses (Complete,Returned,Processing,Shipped,Cancelled) fromGET /api/customers/{user_id}/orders. Clicking Reset Demo Data (#reset-demo-btn,POST /api/demo/resetin either UI 1 or UI 2) opens#reset-progress-modal, which first displays a confirmation dialog (#reset-confirm-panelwith#reset-cancel-btnand#reset-confirm-btn) and then transitions to a 4-stage animated progress view (#reset-running-panel) while refreshing relative UTC timestamps, resettingorder_id: 90124,order_id: 90588, andorder_id: 90910in Cloud Spanner, clearing BigQuerysoa_action_lineagetraces, and clearing persisted chat state inlocalStorage. - ADK 2.0 customer support chat: Embeds a sticky scrollable chat assistant
(
#chat-messages, streaming fromPOST /api/chat/refund/streamwith fallback toPOST /api/chat/refund) with per-persona chat history (chatHistoryByUser[userId]), pending Turn 1 confirmation state (pendingOrderByUser[userId]), and the active customer persona (activeUserId) persisted across/shopand/consolenavigation vialocalStorage(soa_chat_history_by_user,soa_pending_order_by_user, andsoa_active_user_idmanaged byloadPersistedChatState,savePersistedChatState, andclearPersistedChatState), an active persona badge (#chat-persona-label), and a Clear Chat button (#clear-chat-btn) where customers ask questions or request refunds in natural language (using90124,ORD-90124, conversational cues, or storefront items they never purchased viaunmatched_productdetection) or through 1-click persona-aware prompt chips (ORD-90124,ORD-90125, andORD-90126for Customer A;ORD-90588for Customer B;ORD-90910for Customer C, sending localized English or Korean prompts matching the active UI language). Prompt chips with an explicitORD-<id>resolve Step 1 (IntentAgent) directly and reserve the livegemini-3-flash-preview(ThinkingLevel.MINIMALand a 4-second timeout) call for Step 5 (ResponseAgent), while natural-language prompts execute live Gemini calls in both Step 1 and Step 5. While the backend workflow runs,consumeRefundStreamandupdateAgentLoadingStepstream live[1/5]..[5/5]per-node status and elapsed milliseconds into#agent-loading-stepinside#agent-loading-indicator, disable duplicate submissions, and automatically restore keyboard focus (chatInput.focus({preventScroll: true})) after prompt submission. Each agent reply displays the natural-language explanation inside a status-tinted.agent-reply-calloutbox above theWorkflow Telemetry & Lineage Metadatablock, renders product thumbnails on confirmation/verdict cards and synchronized.candidate-order-chipselection buttons, and provides an Inspect in Data Engineer Console deep link (/console?trace_id=...). Both interfaces share an identical top navigation bar for switching between/shopand/console.
UI 2: Data Engineer Investigation Console (/console)¶
UI 2 (Data Engineer Investigation Console, data_engineer_console_url)
provides an operational monitoring and forensic investigation workbench:
- Live refund request feed: Lists incoming customer refund requests (
GET /api/traces), ADK 2.0 execution trace IDs (trace_id), customer IDs, target order IDs, policy verdicts (APPROVED,DENIED,PENDING_CONFIRMATION,ORDER_LIST,ORDER_INFO, orPOLICY_INFO), and Spanner Graph Query Language (GQL) execution latencies (latency_ms). At initial lab launch, before a student submits a refund request,soa_action_lineagestarts empty and displays a guided banner with a link to/shop, while keeping the Cloud Spanner Context Graph workbench and Policy Document (U2G) and Knowledge Catalog Inspector ready for inspection. - Interactive dual-graph visualizer and stacked node inspector (Cytoscape.js):
Queries both graph engines through
GET /api/traces/{trace_id}/graphand renders the refund evaluation subgraph across three color-coded node layers:- Cloud Spanner Relational-to-Graph (R2G) nodes:
users,orders(target order and historical returned orders whentarget_order_idis present),inventory_items,products, anddistribution_centersconnected byplaces,contains_item,is_product, andsupplied_byedges. - Cloud Spanner Unstructured-to-Graph (U2G) policy nodes:
policies, tier-matchedpolicy_conditions(COND-REFUND-STD-100D-30DorCOND-REFUND-VIP-100D-30D), andpolicy_restrictionsconnected bygoverned_by,requires_condition, andenforces_restrictionedges. - BigQuery Action Lineage nodes:
AgentSession,WorkflowNode,PolicyEvaluation, andAgentActionconnected byexecuted_node,evaluated_policy, andtriggered_actionedges, and joined across engines bytargets_order(AgentSessiontoorders) andreferences_policy(PolicyEvaluationtopolicies).
- Cloud Spanner Relational-to-Graph (R2G) nodes:
Clicking any node or edge populates the full-width Node Property Inspector
panel (#node-inspector, stacked below #cy-canvas) with formatted JSON
(highlightJson) showing its Cloud Spanner or BigQuery attributes.
- Policy document (U2G) and Knowledge Catalog inspector with interactive
modals: Displays the Knowledge Catalog semantic contract (
#catalog-contract-view) and extracted U2G policy triples (#u2g-triples-view,POL-REFUND-STD-V1withSTANDARDandVIPcondition nodes) fromGET /api/governancewith JSON color formatting, paired with two expanded explanatory headers and modal dialogs:- Knowledge Catalog Semantic Contract (
#preview-catalog-contract-btnopening#catalog-contract-modal): Explains how Knowledge Catalog binds abstract policy terms (ReturnPolicythresholds) to canonical SQL/GQL expressions on Cloud Spanner (OperationalContextGraph). Clicking Preview Glossary & Contract opens a modal with a Semantic Governance Flow pipeline banner and two tabs: Overview & Governed Terms (#catalog-contract-overview-view, detailing what the contract is, its purpose in preventing LLM metric drift, how Step 2, Step 3, and Step 4 consume it, and cards for the three governed glossary termsrolling-100d-refund-count,order-age-days, andcustomer-loyalty-tierwith their target tables and SQL/GQL expressions) and Raw Glossary JSON (#catalog-contract-raw-view). - Policy Document (U2G) & Extracted Triples (
#preview-policy-doc-btnopening#policy-doc-modal): Explains how corporate policy prose indata/policies/return_policy_v1.mdis compiled into structured U2G nodes (policies,policy_conditions,policy_restrictions) indata/policies/u2g_policy_triples.json. Clicking Preview return_policy_v1.md opens a modal with an Unstructured-to-Graph (U2G) Conversion Pipeline banner and two tabs: Rendered Policy (#policy-doc-rendered-view) and Raw Markdown (.md) (#policy-doc-raw-view).
- Knowledge Catalog Semantic Contract (
- Built-in 3-tab GQL query workbench (read-only guarded): Provides runnable
query templates across three tabs, pre-filling the active
GCP_PROJECT_ID,GCP_REGION,SPANNER_CONNECTION_ID, and selectedtrace_id, with structured-- Purpose / Target Engine / How It Works / Information Gatheredheader comments and live SQL/ISO GQL keyword coloring (#query-highlight-view,highlightSqlGql) (see docs/demo-walkthrough.md):- Cloud Spanner Context Graph (
OperationalContextGraph): Runs ISO GQL inside a Cloud Spanner read-only snapshot (database.snapshot()) throughPOST /api/query/spanner. - BigQuery Action Lineage Graph (
ActionLineageGraph): Runs ISO GQL with a read-onlySELECT/GRAPH_TABLEstatement guard (with a preset SQLJOINtemplate toggle, automatic single-trace vs. all-denials scoping inbuildBqGqlDenialPreset, and preset fallback mapping whenbq_graph_mode == "sql_fallback") throughPOST /api/query/bigquery. - Federated Spanner Data Boost audit (
spanner-data-boost): UsesEXTERNAL_QUERYover thespanner-data-boostconnection to push a scoped Cloud SpannerOperationalContextGraphGQL query to Spanner Data Boost compute and join the operational results with BigQuerysoa_action_lineagetraces throughPOST /api/query/bigquery.
- Cloud Spanner Context Graph (