diff --git a/CHANGELOG.md b/CHANGELOG.md
index f0b8b0b6..6cf5d719 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -125,6 +125,8 @@ Releases up to 2.63.0 are listed in
orchestrator-neutral ([#2099])
- The data-modeling template asks for one naming convention per store and marks
its relational rules ([#2100])
+- The deployment template keeps target-neutral rules and drops its per-target
+ product choices ([#2101])
### Deprecated
@@ -203,6 +205,7 @@ Releases up to 2.63.0 are listed in
[#2098]: https://github.com/solid-ai-dev/solid-ai-templates/pull/2098
[#2099]: https://github.com/solid-ai-dev/solid-ai-templates/pull/2099
[#2100]: https://github.com/solid-ai-dev/solid-ai-templates/pull/2100
+[#2101]: https://github.com/solid-ai-dev/solid-ai-templates/pull/2101
## [2.90.0] - 2026-09-12
diff --git a/docs/migrating-to-v3.md b/docs/migrating-to-v3.md
index f82f5870..0d140300 100644
--- a/docs/migrating-to-v3.md
+++ b/docs/migrating-to-v3.md
@@ -61,6 +61,7 @@ receives nothing (ADR-051).
| The eight-stage pipeline order, its push and tag triggers, the three-environment minimum, the post-publish deploy hook | `base-cicd` | removed; the gates, packaging once, DAST before production and artifact promotion remain |
| Kubernetes: namespaces, two replicas per service, probes, PodDisruptionBudget, ConfigMap secrets | `base-containers` | removed; resources as code and the readiness gate remain, orchestrator-neutral |
| Exact names: plural snake_case tables, `is_` booleans, `
_id` keys, alphabetical junctions, `ix_` and `ux_` indexes | `base-data-modeling` | one convention per store, recorded in the context file; relational rules say so |
+| Per-target product choices: managed CAs, `step-ca`, F5 and MetalLB, Route 53 and Consul, Harbor and Athens, Vault topologies | `base-deployment` | removed; each section keeps its ID and the rules that hold on any target |
| The numbered-document check after concurrent merges, the first-CI-run rule for a check on its own change | `base-git` | this repository's playbook; the `check-heading-numbers` hook still ships |
| The submodule update after a pin bump, the base64 bundle mask, the `.vscode` allowlist | `base-git` | removed; a neutral editor-settings rule remains |
| Factory classmethods; `*-overlay.png` naming | `base-oop`, `base-measurement` | neutral rules remain |
diff --git a/templates/infra/deployment.md b/templates/infra/deployment.md
index c4bfea48..bb651fe7 100644
--- a/templates/infra/deployment.md
+++ b/templates/infra/deployment.md
@@ -1,172 +1,79 @@
# Base — Deployment
[ID: base-deployment]
-Cross-cutting deployment rules. Covers deployment targets, certificates, load
-balancing, service discovery, registries, secrets, and network assumptions.
-Applies to every service regardless of language or framework.
+Deployment rules that hold on any target: certificates, load balancing,
+service discovery, registries, secrets, and network assumptions. The
+products and topology a team adopts belong in its own stack or platform
+template.
## Deployment targets
[ID: base-deployment-targets]
-Declare the deployment target explicitly in every project's context file.
-All other rules in this document are qualified by target.
-
-| Target | Description |
-|--------|-------------|
-| `cloud` | Public cloud (AWS, GCP, Azure) — managed services, external CA, public DNS |
-| `hybrid` | On-premises + cloud — private CA for internal traffic, public CA for external |
-| `offline` | Air-gapped — no internet access; all dependencies pre-mirrored internally |
-
-A project may support more than one target. List all that apply and note
-which sections of configuration differ per target.
+- Declare each deployment target in the project's context file: cloud,
+ hybrid, offline (air-gapped), or another the project names
+- Note which configuration differs per target
## Certificates and PKI
[ID: base-deployment-certs]
-**Cloud:**
-- Use a managed CA: AWS ACM, GCP Certificate Manager, or Let's Encrypt via
- ACME — do not manage certificates manually
-- Automate renewal — never set a manual expiry reminder as the sole safeguard
-- Terminate TLS at the load balancer or ingress; internal service-to-service
- traffic may use mTLS via a service mesh
-
-**Hybrid:**
-- Run an internal CA (Smallstep `step-ca`, HashiCorp Vault PKI, or CFSSL)
- for all internal services
-- Use a public CA (Let's Encrypt, ACM) for externally reachable endpoints only
-- Distribute the internal root CA cert to all nodes via configuration
- management — never distribute it manually
-- Automate internal certificate rotation; treat certificates expiring without
- renewal as an incident
-
-**Offline:**
-- Internal CA is the only CA — no ACME against public endpoints
-- Run an internal ACME server (Smallstep `step-ca` supports this) so services
- can renew certificates automatically without internet access
-- Pre-distribute the root CA cert in the base OS image or via configuration
- management before first deployment
-- Certificate revocation via internal CRL or OCSP responder — no external OCSP
+- Automate certificate issuance and renewal — never rely on a manual expiry
+ reminder alone
+- Treat a certificate expiring without renewal as an incident
+- Distribute every trusted root certificate through configuration
+ management or the base image, never by hand
+- Renew certificates and check revocation against endpoints the target can
+ reach; an offline target uses internal ones only
## Load balancing and reverse proxy
[ID: base-deployment-lb]
-**Cloud:**
-- Use the cloud provider's managed load balancer (AWS ALB/NLB, GCP Load
- Balancing, Azure Application Gateway)
-- Prefer application-layer (L7) load balancing for HTTP services — enables
- path-based routing, header inspection, and health checks
-- Do not run a self-managed reverse proxy in front of a managed LB unless
- there is a specific requirement (e.g. custom WAF rules)
-
-**Hybrid:**
-- External traffic: managed cloud LB or hardware appliance (F5, Citrix ADC)
- at the network boundary
-- Internal traffic: software reverse proxy (NGINX, HAProxy, Traefik) or
- service mesh (Istio, Linkerd) for east-west routing
-- Ensure the internal LB is aware of both on-prem and cloud service endpoints
-
-**Offline:**
-- Software load balancer only: HAProxy, NGINX, or Traefik — all run fully
- offline with static or service-discovery-driven configuration
-- Hardware appliances: F5 BIG-IP, Citrix ADC — common in government and
- defence networks; configure via local management plane, not cloud APIs
-- Kubernetes bare-metal: use MetalLB for `LoadBalancer` service type;
- configure address pools from the local IP range
+- Route public ingress through a load balancer or reverse proxy that
+ health-checks its backends; never make an instance directly
+ internet-routable
+- Prefer application-layer (L7) load balancing for HTTP services — it
+ enables path-based routing, header inspection, and health checks
## Service discovery and DNS
[ID: base-deployment-dns]
-**Cloud:**
-- Use the cloud provider's DNS service (Route 53, Cloud DNS, Azure DNS)
-- Use cloud-native service discovery where available (AWS Cloud Map,
- Kubernetes CoreDNS)
-- Services should resolve each other by DNS name — never hardcode IPs
-
-**Hybrid:**
-- Internal DNS: BIND or CoreDNS — authoritative for all internal zones
-- Split-horizon DNS: internal zones resolve to private IPs; public zones
- resolve to public IPs
-- Dynamic service registration: Consul or etcd, integrated with DNS via
- Consul DNS or CoreDNS plugins
-
-**Offline:**
-- Internal DNS is the only DNS — no public resolver fallback
-- All hostnames must resolve within the internal DNS zone before deployment
-- Dynamic service discovery: Consul or etcd running on internal infrastructure
-- NTP: sync all nodes from an internal time server — clock skew causes
- certificate validation failures and distributed system bugs
+- Resolve services by DNS name or service discovery — never hardcode IPs
+- Confirm every hostname a service needs resolves on its target before
+ deployment
+- Sync every node's clock from a time source the target can reach — clock
+ skew breaks certificate validation and distributed systems
## Container and artifact registries
[ID: base-deployment-registries]
-**Cloud:**
-- Use a managed registry: AWS ECR, GCP Artifact Registry, GitHub Container
- Registry, or Docker Hub (private)
-- Enforce image signing and scan all images for vulnerabilities before
- promotion to production
-
-**Hybrid:**
-- Internal registry (Harbor, JFrog Artifactory, Sonatype Nexus) proxies and
- caches images from public registries
-- Air-gapped segments pull from the internal registry only — no direct
- internet access from those segments
-- Mirror required base images and dependencies into the internal registry
- as part of the build pipeline
-
-**Offline:**
-- All images and packages must be mirrored before the system is air-gapped:
- - Container images → Harbor, Artifactory, or Nexus
- - Go modules → Athens module proxy
- - Python packages → devpi or Artifactory PyPI proxy
- - npm packages → Verdaccio or Artifactory npm proxy
-- Set `GOPROXY`, `PIP_INDEX_URL`, and `.npmrc` to point to internal mirrors
- in all build environments
-- Scan and approve all dependencies at the boundary before mirroring —
- treat the mirror as a trusted internal supply chain artefact
+- Sign every image and scan it for vulnerabilities before promotion to
+ production
+- Mirror every image and package into an internal registry where the
+ target cannot reach public ones, and point every build environment at
+ the mirror
+- Scan and approve each dependency before mirroring it — the mirror is a
+ trusted supply chain
## Secrets management
[ID: base-deployment-secrets]
-**Cloud:**
-- Use the cloud provider's secrets service (AWS Secrets Manager, GCP Secret
- Manager, Azure Key Vault) or HashiCorp Vault with a cloud backend
-- Never pass secrets as environment variables baked into images — inject at
- runtime via the secrets service or a Kubernetes `Secret` mounted as a volume
+- Inject secrets at runtime from a secrets service; never bake them into an
+ image
- Rotate secrets automatically; alert on rotation failures
-
-**Hybrid:**
-- HashiCorp Vault with a replicated backend spanning on-prem and cloud, or
- separate Vault clusters with cross-cluster replication
-- Services authenticate to Vault using platform identity (IAM role, K8s
- service account) — no static Vault tokens in configuration files
-
-**Offline:**
-- HashiCorp Vault (runs fully offline), CyberArk, or a hardware HSM
-- Vault unsealing must not depend on an external KMS — use Shamir secret
- sharing with a defined key custodian process, or an internal HSM for
- auto-unseal
-- Establish a documented break-glass procedure for Vault recovery
+- Authenticate services to the secrets service by platform identity — no
+ static tokens in configuration files
+- Keep the secrets service's unseal and recovery free of anything the
+ target cannot reach, and document a break-glass procedure
## Network assumptions
[ID: base-deployment-network]
-Document network assumptions explicitly in the project context file.
-Do not rely on implicit network access that may not exist in all targets.
-
-**Cloud:**
-- Outbound internet access available unless restricted by VPC policy
-- Public ingress via load balancer; services are not directly internet-routable
-- Assume DNS, NTP, and package registries are reachable
-
-**Hybrid:**
-- Define which network segments have internet access and which do not
-- Services crossing the boundary must go through a defined ingress/egress point
-- Firewall rules must be documented and version-controlled alongside the service
-
-**Offline:**
-- No outbound internet access — any code that calls an external URL will fail
-- Audit all dependencies for hidden external calls (telemetry, update checks,
- licence validation) — disable or patch before deployment
-- All required endpoints (DNS, NTP, registry, CA, OCSP) must be reachable
- within the internal network before the service starts
-- Document the full list of required internal endpoints in the project README
+- Document network assumptions in the project's context file: which
+ segments reach the internet, and the internal endpoints a service needs
+ (DNS, NTP, registry, CA, OCSP)
+- Route traffic that crosses a network boundary through a defined ingress
+ or egress point
+- Keep firewall rules in version control beside the service
+- Audit dependencies for hidden external calls (telemetry, update checks,
+ licence validation) on a target without outbound internet, and disable
+ them before deployment
+- Make every required endpoint reachable before the service starts
diff --git a/templates/manifest.yaml b/templates/manifest.yaml
index cd6d88ac..6691cdd4 100644
--- a/templates/manifest.yaml
+++ b/templates/manifest.yaml
@@ -56,7 +56,7 @@ base:
description: Env vars, secrets, fail-fast validation
- id: base-deployment
file: templates/infra/deployment.md
- description: Deployment targets (cloud/hybrid/offline), certs, LB, registries, secrets
+ description: Deployment targets, certs, load balancing, DNS, registries, secrets, network
- id: base-data-quality
file: templates/data/data-quality.md
description: Data sourcing, completeness, freshness, research, scoring — data-heavy projects
diff --git a/tests/baselines/template-quality.txt b/tests/baselines/template-quality.txt
index 89e0dec3..6679eeec 100644
--- a/tests/baselines/template-quality.txt
+++ b/tests/baselines/template-quality.txt
@@ -40,6 +40,6 @@ templates/frontend/static-site.md 84.2
templates/frontend/ux.md 94.3
templates/infra/cicd.md 95.7
templates/infra/containers.md 95.2
-templates/infra/deployment.md 95.4
+templates/infra/deployment.md 99.4
templates/security/devsecops.md 100.0
templates/security/security.md 96.1