Skip to main content

Temporal in UpsQuad — Architecture & Licensing

UpsQuad · Engineering Reference · Decision Record Companion

How Temporal fits our system — and why we're licensed to ship it.

Decided 2026-07-15 (ADR-0023, PRD core#1783). Temporal replaces only the durability plumbing under our workflow engine. Everything customers pay us for — governance, audit, clearance, cost, the DAG experience — remains UpsQuad code.

PRDADR-0023TrackerBuild
core#1783PR core#1784core#1786W0/W0.5 in flight (WF-01…WF-10)
Open the fully-styled brief

This page carries the full text of the brief so it is searchable in this site and retrievable by agents through the docs RAG index. For the source page in its original visual format — the layered SVG architecture diagram, the licensing panel, and the exact typographic treatment — open the fully-styled brief →.

The brief is served verbatim from docs-site/static/briefs/temporal-architecture.html; it is a rebuilt view over the same content — never an editable store.

Architecture — one run = one durable Temporal workflow; every action = our Go code

Trigger flows down the left; live status flows up the right. Temporal (blue) holds the run's spine — position, timers, signals, retries. It executes none of our business logic: every box it calls is an activity in our worker, wrapped by the governance choke-point (green).

app.upsquad.ai — Workflows UI (frozen 16-RPC contract, already shipped) definitions · 3-step wizard · instances · live DAG · timeline/logs · Approvals queue context-engine · WorkflowService CreateWorkflow (validator) · TriggerWorkflow · Pause/Cancel/ResumeRun SetWorkflowEnabled → Temporal Schedules · definitions stay in OUR tables Live-DAG streams (StatusHub) StreamRunStatus / StreamRunLogs fed by Postgres LISTEN/NOTIFY — unchanged trigger / control RPCs live node updates ↑ TEMPORAL — durable run spine (MIT-licensed OSS, self-hosted) RunWorkflow (one per run) deterministic interpreter walking OUR JSON DAG definition, step by step ID run:{org}:{run} → exactly-once trigger survives crash/deploy via event replay durable timers gate timeout_minutes is a real timer — fires even with all workers down signals approval_decision pause · resume · cancel buffered in history, race-free Schedules + retries cron per workflow, overlap-skip · backoff policies per activity StartWorkflow · SignalWorkflow · ScheduleClient AGENT-ORCHESTRATOR WORKER — all business logic runs HERE, as activities (our Go code) Govern → Audit → Cost 4-layer clearance cascade wraps EVERY hop · hash-chained audit (tamper-evident) · cost accrual THE MOAT — unchanged, ADR-0015 ExecuteAgentStep SessionExecutor → agent session (T1-T7 resolved tools/models/MCP, guardrails, budget gates) → LLM turn heartbeats · idempotency anchor usage → llm_usage_events RunProjector + ApprovalGate projects every transition into workflow_runs/actions (idempotent) gates open rows in the SAME Approvals queue the org UI uses; decision → signal → run resumes activities execute on task queues wf-runs / wf-activities Postgres · upsquad DB (per-tenant RLS on every activity tx) workflows · workflow_runs/actions (→ NOTIFY → live DAG) · coordinator anchors governance_approvals · hash-chained audit · llm_usage_events (cost truth) NOTIFY on write — this is what lights the UI with zero client changes Postgres · temporal DBs (separate) temporal + temporal_visibility databases direct connection (not pgbouncer) Temporal's own schema tooling; capped conns run history/state Phase 0: everything on the dev-box compose stack — $0 infra. Phase 1 (Cloud Foundation): Temporal → GKE Helm or Temporal Cloud behind the same seam.
Temporal (MIT OSS — plumbing only) UpsQuad moat (governance/audit/cost/UX — unchanged) Existing services & stores

Layer by layer

  • app.upsquad.ai — Workflows UI (frozen 16-RPC contract, already shipped): definitions · 3-step wizard · instances · live DAG · timeline/logs · Approvals queue.
  • context-engine · WorkflowService: CreateWorkflow (validator) · TriggerWorkflow · Pause/Cancel/ResumeRun · SetWorkflowEnabled → Temporal Schedules. Definitions stay in OUR tables. Live-DAG streams (StatusHub): StreamRunStatus / StreamRunLogs, fed by Postgres LISTEN/NOTIFY — unchanged.
  • TEMPORAL — durable run spine (MIT-licensed OSS, self-hosted):
    • RunWorkflow (one per run) — a deterministic interpreter walking OUR JSON DAG definition step by step; ID run:{org}:{run} → exactly-once trigger; survives crash/deploy via event replay.
    • durable timers — a gate's timeout_minutes is a real timer that fires even with all workers down.
    • signalsapproval_decision, pause · resume · cancel, buffered in history, race-free.
    • Schedules + retries — cron per workflow, overlap-skip · backoff policies per activity.
  • AGENT-ORCHESTRATOR WORKER — all business logic runs HERE, as activities (our Go code):
    • Govern → Audit → Cost — the 4-layer clearance cascade wraps EVERY hop; hash-chained (tamper-evident) audit; cost accrual. THE MOAT — unchanged, ADR-0015.
    • ExecuteAgentStepSessionExecutor → agent session (T1-T7 resolved tools/models/MCP, guardrails, budget gates) → LLM turn; heartbeats; idempotency anchor; usage → llm_usage_events.
    • RunProjector + ApprovalGate — projects every transition into workflow_runs/actions (idempotent); gates open rows in the SAME Approvals queue the org UI uses; decision → signal → run resumes.
  • Postgres · upsquad DB (per-tenant RLS on every activity tx): workflows · workflow_runs/actions (→ NOTIFY → live DAG) · coordinator anchors · governance_approvals · hash-chained audit · llm_usage_events (cost truth). NOTIFY on write is what lights the UI with zero client changes.
  • Postgres · temporal DBs (separate): temporal + temporal_visibility databases; direct connection (not pgbouncer); Temporal's own schema tooling; capped conns.

Deployment phasing

  • Phase 0 — now. Temporal runs as one container in the existing dev-box compose stack, persisting to two extra databases on our own Postgres. $0 incremental infra. Engineers use the free single-binary dev server locally; CI uses the time-skipping test kit.
  • Phase 1 — at the Cloud Foundation move. Same code, re-pointed: self-hosted on GKE (Helm, ~$400–900/mo infra) or Temporal Cloud (managed, $100–500/mo entry). Ashik's call — it's a connection string and a namespace, not a rewrite. In-flight runs drained during a planned cutover window.

Licensing — why we can ship this inside a commercial, multi-tenant enterprise product

Every Temporal component we use is under The MIT License — verified directly from the LICENSE files in each repository (fetched 2026-07-12, re-confirmed at adoption). The operative text, verbatim:

The MIT License

Copyright (c) 2025 Temporal Technologies Inc. All rights reserved. Copyright (c) 2020 Uber Technologies, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED…

Legal record

The clause above is a legal record and is reproduced verbatim. The full, unabridged MIT text (pinned to the exact adopted version) is carried in ADR-0023 Appendix A (PR core#1784) and the WF-05 dependency PR (core#1791). The fully-styled brief renders it in the licensing panel with the operative clauses highlighted.

ComponentRepositoryLicense (verified)
Temporal servergithub.com/temporalio/temporalMIT
Go SDK (in our binaries)github.com/temporalio/sdk-goMIT
Web UIgithub.com/temporalio/uiMIT
Helm charts (Phase 1)github.com/temporalio/helm-chartsMIT

What the license clears us to do:

  • Selling a service built on it is expressly permitted. The grant covers "use… sublicense, and/or sell" with "without restriction" — there is no separate commercial tier, no revenue clause, no "internal use only" carve-out. Running Temporal under UpsQuad and charging customers is squarely inside the license.
  • SaaS use carries effectively zero obligations. The single MIT condition (keep the copyright + permission notice) attaches to copies of the Software. Our SaaS never distributes Temporal to customers — it runs server-side — so the condition barely engages.
  • On-prem / enterprise deployments are also covered. If we later ship Temporal inside a customer-installed bundle (ADR-0002 enterprise tier), we must include the notice above in the distribution — a text file. That is the entire obligation. No source-disclosure duty (not copyleft), no network clause (unlike AGPL), no field-of-use limits (unlike n8n's Sustainable Use License or Dify's multi-tenant prohibition).
  • No retroactivity risk. A future Temporal relicense (the Redis/Terraform pattern) cannot reach versions already released under MIT; worst case we pin or follow a community fork. Our dependency PR (WF-05, core#1791) records the exact version + license text at adoption.
  • ⚠️ Trademark is separate from copyright. MIT licenses the code, not the "Temporal" name/logo. We describe the capability ("durable workflow execution"), we don't brand our product with their marks — normal practice, noted for marketing.
  • ⚠️ Temporal Cloud is a different animal. The managed service runs under its own commercial terms of service — relevant only if Ashik picks Cloud at Phase 1, and it's a vendor contract, not a code license.
  • ⚠️ Standard diligence still applies. Transitive dependencies get a license scan in the WF-05 dependency PR (all Temporal first-party deps are MIT/Apache-2.0), and for enterprise contracts where customers demand license schedules, this page + the ADR give counsel everything needed. This is engineering due diligence, not a substitute for legal review on specific customer paper.

Durable records: ADR-0023 (PR core#1784) carries this analysis with citations; the WF-05 dependency PR pins the version and license text; PRD core#1783 records the adoption decision and deployment phasing.

References

Prepared 2026-07-15 · UpsQuad workflows build · companion to ADR-0023 (PR core#1784) · PRD core#1783 · Tracker core#1786 · Deps core#1791 (WF-05)