Skip to content

Team standards

The language, framework, deploy and tooling baseline for every surface.

Updated View as Markdown

The standard for each surface comes first, followed by the platform-wide baseline. Each team’s pages list the exact tools used in each area.

By surface

  • Language: C#
  • Framework: WPF / NinjaScript
  • Deploy: signed installer

Platform-wide

Concern Standard
Source control GitHub
Build & CI GitHub Actions on self-hosted runners; reusable actions from NT-NinjaTrader/gh-actions. See CI/CD.
CI to cloud auth Workload Identity, no long-lived keys. See security.
Containers & registry Docker to Artifact Registry; build once and promote.
Infrastructure Terraform on GCP (Atlantis on PRs)
Secrets GCP Secret Manager via Workload Identity (external-secrets operator in-cluster). See security.
Feature flags Statsig. See feature flags.
Client error tracking Sentry (web, mobile, desktop)
Service error tracking OpenTelemetry with structured logs, no dedicated tracker. See observability.
Telemetry & tracing OpenTelemetry to Cloud Trace
Logs Cloud Logging (log-based metrics drive alerting)
Dashboards & alerts Cloud Monitoring, defined in Terraform
Paging PagerDuty. See release and incidents.
Product analytics Statsig Web Analytics
Consent OneTrust
Data warehouse BigQuery
Domain model Defined once in tradovate/master-scheme, generated downstream. See architecture.

Version-support policy

A language name alone can become outdated. Set the supported version range so readers know the minimum version, not just the tool name.

Surface Baseline Support window
Backend JVM JDK LTS 17 and 21 Track the LTS cadence; the drop rule is open (see open questions)
Backend Scala Scala 2.13 (current) Scala 3 direction, see the note below
FCM Python 3.12+ LTS-supported CPython only
Web / services Node LTS only Even-numbered active or maintenance LTS
Mobile Dart / Flutter, current stable Track upstream stable
Desktop .NET, current LTS Track the .NET LTS cadence

Keep the JVM on Java SE LTS releases. Set the minimum version in the build config, not just in prose:

// build.sbt, the version floor is enforced, not documented
ThisBuild / scalaVersion := "2.13.14"
ThisBuild / javacOptions ++= Seq("--release", "17")
ThisBuild / scalacOptions ++= Seq("-release:17", "-Werror", "-Wunused:all", "-deprecation")

Quality-tooling baseline

Each surface sets a formatter, a linter, and a type or static-analysis check. These are the specific checks that the quality gates run in CI.

Surface Format Lint / static analysis Types
Scala scalafmt scalafix compiler -Werror
Python ruff format ruff mypy
TypeScript Prettier ESLint tsc strict
Dart dart format dart analyze built-in
C# dotnet format Roslyn analyzers built-in
Go gofmt go vet + staticcheck compiler
Rust rustfmt Clippy compiler

Run locally the same checks that CI runs:

Build and dependency management

List the build and dependency manager for each surface so “one build toolchain” has a clear meaning.

Surface Build / dependency manager
Scala sbt + coursier
Python uv
TypeScript pnpm
Dart pub
C# NuGet
Go Go modules
Rust Cargo

Commit the lockfile for every project. Pin direct dependencies. Use Renovate to keep dependencies current, so the minimum version stays clear instead of drifting:

// renovate.json, org-wide dependency currency policy
{
  "extends": ["config:recommended"],
  "lockFileMaintenance": { "enabled": true },
  "vulnerabilityAlerts": { "labels": ["security"] }
}

Supply chain

The registry process is build once and promote (see The Twelve-Factor App build/release/run separation and the Artifact Registry docs). Add these supply-chain rules:

  • Generate an SBOM at build time and retain it with the artifact.
  • Scan dependencies with Renovate or Dependabot; treat vulnerability alerts as work.
  • Sign images and record build provenance so a promoted digest is verifiable downstream.

Governance

This table is a standard, not a suggestion. Changes require review.

  • An owner group owns the table and reviews it on a set cadence; the exact owner and cadence are still being ratified (see the note below).
  • Changing an existing standard requires an ADR that records the decision and its context.
  • Introducing a new language or tool routes through the exceptions process before it lands here.
  • The shared CI toolchain lives in NT-NinjaTrader/gh-actions; reuse those actions rather than re-implementing per repository.
  • Define the domain model once in tradovate/master-scheme, and generate downstream. Never redefine a shared entity in a service.
Navigation

Type to search…

↑↓ navigate↵ selectEsc close