Versioned, Signed, and Tagged
Every deployment is traceable back to a specific commit by a specific author. Version numbers are durable; commits are signed; Docker image tags match git refs. If production misbehaves, the first question ("what's running?") always has an answer that's specific enough to pull up the source.
Semantic versioning in the manifest
The project's canonical version lives in the build manifest — Cargo.toml for Rust, package.json for Node, composer.json for PHP. Bump it when you cut a release. CI reads it for image tags.
# api/Cargo.toml
[package]
name = "client-portal-api"
version = "2.0.0"
Semver rules:
MAJOR.MINOR.PATCH- Breaking changes → MAJOR
- New features that don't break existing consumers → MINOR
- Bug fixes / internal changes → PATCH
- Pre-release:
2.0.0-rc.1,2.0.0-beta.3
The Client Portal is on 2.0.0 because it's the second generation of the DTC client portal product (PHP v1 → Rust+SvelteKit v2). Codebase age and semver are independent — a fresh rewrite can legitimately ship as 2.0.0 if it replaces a prior 1.x product.
SSH-signed commits
Every commit from a DTC engineer is SSH-signed via their 1Password SSH agent. commit.gpgsign = true in the repo config. No exceptions, no --no-verify.
git log --show-signature
# Shows SSH signature block on every DTC commit
This ties every line of production code to a cryptographically-verified identity. If a commit shows up with a valid signature matching an authorized public key, we know who wrote it.
Configuration for commit signing lives in the DevOps book's Commit Signing page. New engineers configure this on day one.
Docker tags match git refs
CI/CD produces image tags that let you trace any running container back to a specific commit. The scheme in the Client Portal:
| Branch / trigger | Image tags produced |
|---|---|
Push to development |
dev, {version}-dev, {version}-dev-{short-sha} |
Push to release or v* tag |
latest, release, {version} |
So a container running ghcr.io/dtc-inc/client-portal-api:2.0.0-dev-4161550 can be traced to commit 4161550 directly. No "which version is this?" ambiguity.
latest and dev are floating tags that point at the most recent build. {version}-{sha} is the immutable tag — once pushed, that content never changes.
Git identity per context
Git identity per context
DTC projects use DTC identity (your.name@dtctoday.com). Personal projects use personal identity. Don't let cross-contamination happen — commits under a personal email in a DTC repo pollute the audit trail.
How to configure this, including path-based automation via [includeIf] so you never have to think about it per-repo: Git Identity per Context in the DevOps book.
Version surfaces to the user
The version is shown to end users in the footer of every authenticated page and the login screen. When a customer calls support, they can cite a specific version, which cross-references to a specific build, which cross-references to specific commits.
Implementation: package.json version is imported at build time into a lib/version.ts module that exports a constant. Bumping the manifest automatically bumps the footer on the next build.
Why we do this
- Incident response. Every artifact running in production traces to a known commit by a known author.
- Cryptographic authorship. SSH signing prevents commit spoofing.
- No "which version?" confusion. Version lives in one place (the manifest); it flows automatically to Docker tags, UI footers, logs.
- Auditability. For compliance (CMMC, HIPAA-aligned), a verifiable chain from deployed artifact → commit → author is a requirement, not a nicety.
When this applies
Every DTC-built codebase. Zero exceptions for production systems.
When it does not apply
- Single-file one-shot scripts that aren't deployed (e.g., an ad-hoc migration script that runs once and gets deleted).
- Personal experiments that never touch DTC infrastructure.
Related
- Branding in the Environment, Not the Code — version in the binary, branding in env
- Commit Signing — 1Password SSH agent setup
- Branching Strategy — how branches trigger which image tags
- Semantic Versioning — when to bump which digit
- Docker Image Tagging Strategy — tag shape per branch