matchday-v3 / docs /ARCHITECTURE.md
mzidan000's picture
Publish verified MatchDay v3 source
6d528b3 verified
|
Raw
History Blame Contribute Delete
17.6 kB

Architecture

MatchDay v3 architecture

Component views

The editable Graphviz sources are stored beside each image as .dot files so judges can inspect or regenerate every diagram.

Runtime flow

  1. Vercel serves the Next.js trip workspace. A singleton session bootstrap gives the browser a server-minted, HMAC-signed, HTTP-only anonymous identity before private requests; tampered identities are rejected and replaced.
  2. The Vercel server facade signs every private request with an HMAC over timestamp, nonce, method, path, the SHA-256 digest of the exact forwarded raw query, user ID, and body digest, then calls the Alibaba API origin over HTTPS.
  3. Alibaba Caddy exposes only public health and signed API routes. FastAPI recomputes the query digest from the ASGI raw bytes and rejects query/body tampering, stale signatures, invalid tools, invalid arguments, and cross-user access. Fully authenticated GET/HEAD requests do not consume replay state. Mutating methods atomically commit a valid nonce before endpoint work and reject its replay even when the first handler fails.
  4. Qwen first receives one bounded retrieval of relevant, confirmed fan memories and converts the request into a typed trip intent with an explicit ranking objective. A checkpoint replay reuses that same context without another search. Safety values stated in the current message are separately grounded as one-trip constraints; they override active-trip state and durable memory without rewriting either. Once the fixture is grounded, MatchDay performs at most one additional recall for that exact host-city/date trip namespace and boosts it ahead of global profile facts. Deterministic safety code separately loads every active fan constraint plus only that exact trip namespace.
  5. A dedicated Alibaba worker reads FIFA's first-party 2026 calendar endpoint every six hours. It streams at most 8 MB, requires exactly matches 1-104 and all 16 host cities, normalizes venue/timezone/date/provenance, and atomically upserts PostgreSQL only after whole-feed validation. The API can make one on-demand refresh for a missing or stale fixture; failures preserve the prior cache and enter a five-minute retry cooldown. For flexible prompts, Qwen calls search_fixtures with typed team/host/country/date/stage filters and an explicit coverage mode. Bounded match-list discovery returns up to 16 chronological official candidates. Host-city selection returns one deterministic official representative for every eligible city, up to all 16, and the typed manifest rejects truncation, duplicates, or erased coverage. MatchDay checkpoints discovery before the next model call and rejects any later intent outside that candidate set. No matches produce a specific human clarification. Final verification independently rechecks the selected identity, host, date, and kickoff against fixture grounding.
  6. SerpApi searches Google Flights plus one explicitly selected stay mode: Google Hotels by default or Google Vacation Rentals with vacation_rentals=true. Rental mode requires a provider-reported rental type, keeps only bounded occupancy/room facts, excludes hotel class/free-cancellation flags/accessibility filters and hotel-only memories, and rechecks the property type during exact-offer resolution. The final-city path resolves at most three outbound, three return, and three stay seller tokens with four workers, then uses exact current seller prices before forming at most 27 combinations. Optional Amadeus Transfer Search enriches every bounded combination with four deduplicated, exact-cent core transfer legs and structured cancellation windows before objective-diverse selection. Only production/live Amadeus evidence can enter package totals, refund coverage, or ranking; test/sandbox quotes remain visible contract evidence but are explicitly excluded. Missing or mismatched commercial evidence remains partial/unpriced. An all-city comparison deliberately retains the common flight/stay search basis, performs it once per eligible city with at most four concurrent calls, and excludes transfer fares so cities remain comparable; ORS/OSRM route friction stays separately labelled. The maximum 68-request final-city provider bundle is durably reserved before provider I/O. Untrusted output is reparsed and rebound to exact component IDs, route, time, dates, party, seller, currency, capacity, and source before use.
  7. In parallel with travel search, Open-Meteo fetches only the requested trip window inside its live horizon and OpenStreetMap/Overpass returns a bounded distance-sorted nearby set. When the existing SerpApi credential is configured, two hourly-cached Google Maps searches add strictly classified, in-radius place identities, reported weekly hours, safe public sites, and exact record links; Google evidence is merged source-first with OpenStreetMap, and either source fails open independently. Google price labels are never converted into activity or luggage fees, while tickets, bag acceptance, inventory, and current commercial terms remain explicitly unknown. Optional Unsplash search returns a hotlinked, attributed destination image. Each capability degrades to a typed cached, fallback, or unavailable status; response bodies are bounded before parsing, and no provider key enters browser state.
  8. Deterministic multi-factor ranking adapts cheapest, safest-arrival, closest-to-stadium, or balanced weights across cost, arrival buffer, stadium friction, hotel rating/review confidence, provider-reported free cancellation when available, memory fit, fixture confidence, and provenance. Layovers, transit complexity, stale data, budget, and violated memory constraints become explicit risk penalties. The selected factor vector is persisted in the agent trace and rendered in the trip artifact before conflict rules compare the result with every active memory and explicit trip constraint.
  9. Accessibility and country entry are hard evidence gates. Durable accessibility memories are canonicalized to private sensitivity. MatchDay can add SerpApi's official wheelchair-accessible hotel filter, but it accepts only a live provider-reported amenity and only for an explicitly hotel-scoped wheelchair requirement. Broader accessibility needs remain unresolved. Explicit host-country allow/block lists are current-trip-only, polarity-grounded, and checked against the selected Canada/Mexico/USA host. Passport/visa review text is bounded, rejects document identifiers, is excluded from durable memory tools, and always requires official/human confirmation because MatchDay has no immigration eligibility source. Both unresolved paths preserve the candidate artifact at awaiting_approval, lock booking actions, make no unsupported claim, and are removed from public shares with all private current-constraint text.
  10. Qwen sees only conflict evidence and allowed repair candidates, then selects a repair.
  11. Deterministic code applies the patch and a source-blind validator recomputes component totals, contiguous ranks, selected-winner identity, fixture freshness, context capability/count/provenance consistency, accessibility evidence, entry-country scope/evidence, budget, provenance, and every unresolved constraint.
  12. Immediately before completion, MatchDay reloads current fan memory and the exact fixture-scoped trip memory, then revalidates the result so stale checkpoints cannot publish obsolete proof or cross-trip state.
  13. A completed owner-visible itinerary can be schema-validated into a child run's active-trip checkpoint; it is injected as non-instruction context, the current message remains authoritative, and the child records its parent run/revision and objective-specific revision reason.
  14. Each injected memory records one deduplicated run-use event so future usefulness scores expose evidence source, reuse value, conflict status, outcome impact, recency, and privacy risk.
  15. Grounded memory candidates resolve deterministically to ADD, UPDATE, DELETE, or NONE; identical facts do not create replacement churn, while every real mutation retains provenance and audit lineage. An explicit post-trip package choice can create attributed user_action memory. It influences neutral future ranking but never overrides a current request. PostgreSQL serializes memory mutations per user, and a partial unique index guarantees one active version for each memory identity.
  16. Final-city live package actions are seller-resolved privately before ranking whenever a SerpApi token exists; exact current price and explicit refund evidence are attached only after component identity, dates, party, type, and safe Google checkout URL match. Unknown terms remain partial. The owner-only resolver can refresh a retained private reference and otherwise returns an honestly labelled route/property-and-date search. SerpApi and Amadeus offer/access tokens never enter the browser, run view, public share, or logs; only a hash of a transfer offer identifier is persisted, and a bounded Google POST checkout field is returned only when that exact seller action requires it.
  17. Public share creation stores an immutable allowlisted snapshot on Alibaba. Anonymous reads of immutable pre-v2 records preserve the existing slug but re-project the stored payload through the current allowlist, so a raw legacy snapshot never crosses the public boundary. The public Vercel page receives neither private memory, user identity, model metadata, tool history, nor provider action tokens.
  18. Typed events and checkpoints commit before the next external model call. Interrupted workers become resumable stalls on startup. Material clarification continues the same owner-checked run, and a conditional SQL transition allows only one resume or continuation worker.
  19. Every new, manually resumed, or continued execution atomically claims per-user and global PostgreSQL hourly budgets before Qwen execution. Each attempt has a 12-step planning ceiling and a wall-clock deadline by default, while companion execution state enforces lower durable total model/tool/cost/attempt ceilings across every automatic or manual retry; the attempt ceiling also bounds cumulative retry time.
  20. Owner-scoped recent-run summaries expose persistent trip versions without leaking another user's runs. The browser aborts stale polls, retries transient failures five times, and never lets an old response overwrite a newer run.
  21. /healthz probes the complete v3 database contract—tables, column types/nullability, primary keys, index columns/uniqueness/partial predicates, unique constraints, and foreign keys—but returns only the minimal public readiness object {"status":"ok"} or a generic failure. Startup creates absent additive objects but fails closed instead of rewriting an incompatible existing table. The v3 contract adds a companion share-claim table so retries and concurrent requests reuse one canonical public artifact without mutating or invalidating legacy share URLs. The direct, HMAC-signed operator endpoint /v1/ops/health reports the schema version/fingerprint, fixture status, release identity, and other sanitized diagnostics; ordinary guest identities receive no such telemetry, and the public Vercel facade refuses both the operator namespace root and descendants before creating a guest session. Deployment verification requires minimal readiness from the direct Alibaba endpoint and Vercel facade plus the expected commit and schema contract from the signed direct operator endpoint, then requires the signed facade /v1/me response's non-secret deployment ID to match that same commit before asserting the ECS automatic-release timestamp. PostgreSQL is streamed to a private off-worktree dump before deploy; release-tagged API images preserve application rollback.
  22. Agent execution uses a companion run_executions control record rather than changing the legacy run payload: atomic fencing leases, attempt/model/tool/cost budgets, deadlines, cancellation signals, retry classification, and checkpoint resumes survive API-process loss. Request background tasks provide low-latency dispatch, while a private database-polling worker is the durable recovery path; both contend through the same token and only the current token may heartbeat, reserve work, or checkpoint. Each executor keeps that lease alive from an independent database session while bounded provider I/O is in flight, but an expired lease can never be revived. Signed operator health exposes aggregate counts only, never worker tokens or identities.
  23. Provider capabilities are data, not prompt assumptions. Viator access is gated by the configured Basic/Full/Full+Booking/Merchant tier and sandbox/production environment; destinations, tags, attraction search/details, product search/details, schedules, real-time availability, affiliate redirect, and transactions have distinct evidence ceilings. Explicit attraction intent performs a ten-result destination search and at most three on-demand detail resolutions, binds each attraction back to the selected product and destination, ignores protected free-form provider content, and renders only typed metadata on noindex pages. Product and product-option pickup facts remain separately labelled. Luggage and transfer results are destination-wide catalogs: their starting prices, schedules, terms, and handoff links cannot satisfy the four-leg address/time/party fare contract or enter package totals. Transactional Viator tools are not enabled in this release. openrouteservice is separately constrained to route geometry/distance/duration and cannot contribute fares, refund terms, inventory, availability, or booking proof. Paired Amadeus credentials add only Transfer Search, commercial fares, and refund-term evidence; test is sandbox evidence excluded from package totals/ranking, production is live search evidence, and booking remains disabled/approval-gated. All provider keys remain server-only, and the execution lease must outlast the longest configured agent-provider timeout.

Trust boundaries

Boundary Model-owned Deterministic-owned
Intent interpretation and material clarification schema, timezone, city, and range validation
Memory bounded relevance context plus remember/forget proposal source/value grounding, ADD/UPDATE/DELETE/NONE decision, current-trip precedence, exhaustive active constraints, allowlist, expiry, supersession, ownership, audit, reuse ledger
Travel fixture-filter selection, candidate choice, objective interpretation, and trade-off explanation bounded official discovery, candidate-to-intent binding, provider execution, joint candidate generation, semantic dedupe, accessibility and entry-country evidence gating, fixture freshness, context enrichment, provenance, normalization, multi-factor scoring
Repair candidate choice and concise reason candidate allowlist, mutation, all-constraint recheck
Completion user-facing summary source-blind verification and terminal-state transition

The production database and all private memory stay on Alibaba Cloud. Vercel never connects to PostgreSQL and never receives the Qwen API key.

Private chain-of-thought is never stored or displayed. The timeline shows tool selection, evidence, decisions, and verification outcomes.

Failure behavior

  • Qwen/provider exceptions produce an honest failed or fallback event; no seeded result is presented as live.
  • Weather, nearby-place, and photo providers have separate timeouts and statuses. Missing weather stays unavailable, nearby context may use a labelled curated city fallback, and missing photography keeps the labelled static UI fallback; none can block trip planning or fabricate live evidence.
  • A memory retrieval failure emits memory.unavailable, continues with validated facts already loaded plus conservative defaults, marks the completed result unavailable for personalization, and renders that limitation in the decision trace.
  • A malformed, partial, oversized, or unavailable FIFA response cannot partially mutate the fixture cache. The worker retries failures after five minutes, while user requests receive the last verified cache and a stale/outage warning instead of repeatedly hammering the source.
  • Repeated identical tool calls trip the stall guard.
  • A process restart marks stale nonterminal work as resumable from its per-tool durable checkpoint.
  • Resume and completion revalidate against current active memory and clear stale failure diagnostics.
  • A material question stops at awaiting_approval; the owner can answer it without losing the run's durable context. High-risk or unsupported changes remain human-gated.
  • Simultaneous resume or continue requests cannot schedule duplicate workers.
  • Simultaneous writes to one preference are serialized, versioned, and constrained to one active value.
  • Hourly per-user or global budget exhaustion returns 429 with Retry-After before a run is created.
  • Resume consumes the same guarded execution budget as a new run.
  • One transient browser poll failure retries without discarding the durable run; five consecutive failures become an explicit user-visible stop.
  • A completed state is impossible unless the independent verification contract passes.