R940 Platform Architecture¶
Status: Living platform doc (August 2026). LastVet stack and observability VM operational on pve-r940; VLAN segmentation and HA remain planned.
Audience: Last 1 Enterprises engineering, privacy counsel (NVLSP outreach), VA infrastructure reviewers.
Related documents:
| Document | Role |
|---|---|
| SOVEREIGN_ARCHITECTURE_V2.md | Sovereign on the platform |
| ANGEL_ARCHITECTURE_V2.md | Angel hybrid edge + local lane |
| LASTVET_MIGRATION_PLAN.md | LastVet AWS → R940 cutover |
../../gates/meridian-implementation-spec-pointer.md |
Meridian intelligence layer (peer product, eval gates) |
../lastvet/AWS_ENVIRONMENT.md |
Current AWS inventory (source of truth for migration parity) |
../lastvet/AWS_OPS_CONSOLE.md |
Day-to-day AWS ops map |
../observability/OBSERVABILITY_STACK.md |
Platform observability VM (Prometheus/Grafana/Loki) |
Purpose¶
The Dell PowerEdge R940 is Last 1's sovereign compute platform: a single Proxmox host that runs every Last1 product's data plane under operator control, with one shared exception (GPU inference on inference-01).
Why it exists:
- Data sovereignty — Each product tenant (LastVet, Meridian, Sovereign, Angel local lane) owns its Postgres, object store, and MCP host. No cross-tenant database instances or shared filesystem mounts.
- Pre-PHI migration window — LastVet must move from AWS (
ECS Fargate+RDS Postgres 18+EFS+S3imaging) to the R940 within ~1 month, before VA production approval closes the window for infrastructure changes without production PHI at stake. - Meridian as production gate — Meridian is not a sandbox for LastVet. Its eval harness must be operational and wired into LastVet's deployment pipeline before LastVet production accepts model-serving requests.
- Cost and control — Replace recurring AWS spend for workloads that counsel and CARIN commitments expect to stay under operator custody, while keeping appropriate edges (Cloudflare Pages for LastVet marketing/provider portal; Cloudflare Workers for Angel public API).
Migration horizon: LastVet cutover is the critical path (~4 weeks). Sovereign and Angel migrations proceed in parallel where they do not block LastVet.
Design principles¶
| Principle | Meaning |
|---|---|
| Per-tenant data sovereignty | Each product runs its own database VM (or dedicated Postgres on a product VM). No shared Postgres instance across tenants. |
| Shared inference only | inference-01 runs Ollama with Modelfile aliases (meridian-mistral-7b, sovereign-mistral-7b, angel-mistral-7b, future lastvet-*). Compute-only: no tenant data persisted on the GPU host. |
| No cross-tenant visibility by construction | Separate VMs, separate ZFS datasets, separate VLAN targets, separate Bitwarden projects. Firewall denies east-west traffic except explicitly allowlisted product pairs (e.g., app VM → its own DB VM, app VM → inference-01:11434). |
| Secrets via Bitwarden Secrets Manager | No plaintext keys in .bashrc, committed .env, or git. Runtime injection via bws run or bws secret get. Pre-commit detect-secrets on every repo. |
| Native Ollama API | All products call Ollama /api/chat and /api/embeddings. No OpenAI-compat /v1/* shims (Ryan policy; enforced in Meridian provider code). |
| MCP per tenant | Each product's MCP host runs on that product's app VM. Supervised subprocess pattern for MCP server tools. Internal HTTP API for the product to invoke tools. Not a shared MCP host. |
| LastVet-first | Platform decisions that trade off tenant isolation vs. speed default to protecting LastVet's HIPAA/CARIN posture. |
| Tailscale MagicDNS for inter-service refs | All cross-VM runtime config (connection strings, BWS URLs, systemd env, automation scripts) uses <service>.tailc3bbdc.ts.net MagicDNS hostnames — not raw 192.168.1.x LAN IPs. See Inter-service naming. |
Inter-service naming: Tailscale MagicDNS¶
Decision (August 2026): Option B — Tailscale MagicDNS is the canonical naming layer for every east-west reference between R940 VMs (app → database, app → object store, app → inference, automation → any service).
Rule¶
| Use MagicDNS | Do not use for runtime config |
|---|---|
DATABASE_APP_URL, MIGRATION_DATABASE_URL, MinIO endpoints, Ollama base URLs in product env |
Raw LAN IPs in Bitwarden secrets or checked-in examples |
| Cursor/agent scripts on agent-01 connecting to lastvet-db, lastvet-api, etc. | "Just use 192.168.1.91 because it's on the same switch" |
Postgres host= in connection URLs (with sslmode=require where applicable) |
MagicDNS for public veteran-facing DNS (api.last.vet stays Cloudflare) |
Pattern: <vm-hostname>.tailc3bbdc.ts.net (e.g. lastvet-db.tailc3bbdc.ts.net, inference-01.tailc3bbdc.ts.net).
LAN IPs in the tenant map remain inventory and provisioning references (Proxmox, switch VLAN docs, iDRAC). They are not the stable identity for application or secrets configuration.
Rationale¶
- Stable identity across VLAN segmentation — Target topology moves LastVet staging/prod to VLAN 40/50 and other tenants to dedicated segments. MagicDNS names survive IP renumbering without rewriting every BWS secret.
- One addressing model for humans and automation — Operator SSH, agent-01 deploy scripts, and product VMs all resolve the same hostname. No split-brain where apps use LAN IPs but automation uses Tailscale (or vice versa).
- Encrypted mesh by default — Tailscale WireGuard protects east-west traffic on the admin/production mesh. Postgres TLS on the data plane (see
../lastvet/README-postgres-recovery.md) stacks with transport encryption; MagicDNS keeps configs consistent as TLS is rolled out service-by-service. - Portable secrets — Bitwarden
LASTVET_R940_*_DATABASE_APP_URLand sibling keys encode hostnames that remain valid if a VM is restored to a new LAN lease, as long as the MagicDNS name follows the VM. - Validates the mesh before cutover — If MagicDNS + TLS + pg_hba/firewall rules work in staging, the same pattern extends to prod without a second naming scheme.
Implementation notes¶
| Layer | Requirement |
|---|---|
Postgres pg_hba.conf |
Clients connecting via MagicDNS arrive with their Tailscale source IP, not the LAN IP. Allow explicit /32 (or future Tailscale CIDR) rules for each client role — e.g. lastvet_app from lastvet-api's Tailscale IP — in addition to any LAN rules during flat-LAN transition. |
| Firewalls | East-west allowlists should be expressed in terms of which VMs may talk, documented by MagicDNS name; packet filters may still use IPs until VLAN ACLs are automated. |
| Public ingress | Unchanged: api-staging.last.vet / api.last.vet are Cloudflare + cloudflared (or successor edge). MagicDNS is platform-internal only; never exposed to veterans or the public internet. |
| TLS certificates | Postgres and HTTPS certs should include MagicDNS SANs (self-signed acceptable pre-PHI; CA-signed before VA production). |
First production reference: LastVet staging (lastvet-api → lastvet-db.tailc3bbdc.ts.net, BWS LASTVET_R940_STAGING_DATABASE_APP_URL, pg_hba Tailscale allowlist for lastvet_app) — August 2026.
Tenant map¶
Current flat LAN: 192.168.1.0/24. Target segmented VLANs in Network topology.
| VM | Purpose | VMID | IP | Spec (vCPU / RAM / disk) | ZFS pool | Status |
|---|---|---|---|---|---|---|
| inference-01 | Shared Ollama 0.32.6, T4 GPU passthrough, Modelfile aliases | confirm in Proxmox | 192.168.1.40 |
GPU host; disk for model weights | tank-fast |
Operational |
| meridian-eval | Meridian eval harness runner (last1-meridian), CI/ad-hoc suites |
confirm | 192.168.1.41 |
Batch compute (size TBD) | tank-fast |
Operational |
| meridian-rag | Meridian Postgres 16.14 + pgvector 0.6.0; RAG index | confirm | assign / confirm | DB VM + data disk | tank-fast (data at /data/postgres-main) |
Operational |
| sovereign-app | Odysseus FastAPI, Sovereign UI, MCP host, sidecars | confirm | 192.168.1.70 |
App tier | tank-fast |
Operational (bring-up) |
| sovereign-mem | Sovereign MemPalace data: Postgres + pgvector | confirm | 192.168.1.71 |
200 GB data disk typical | tank-fast |
Operational (bring-up) |
| angel-local | Angel batch/eval workstation, local pgvector experiments, MCP host | confirm | 192.168.1.80 |
16 vCPU / 48 GB / 200 GB data | tank-fast |
Operational |
| agent-01 | Automation / Cursor agent host, gh, repo clones |
confirm | assign / confirm | Dev tooling | tank-fast |
Operational |
| lastvet-api | LastVet Express API (staging + prod systemd instances) | 107 | 192.168.1.90 |
8 vCPU / 16 GB / 100 GB | tank-fast |
Operational |
| lastvet-db | Postgres 18, lastvet_master + lastvet_app roles |
108 | 192.168.1.91 |
8 vCPU / 32 GB / 100 GB + 1 TB data | tank-fast |
Operational |
| lastvet-imaging | S3-compatible object store (MinIO) for imaging uploads | 109 | 192.168.1.92 |
4 vCPU / 8 GB / 100 GB + 3 TB bulk | tank-bulk-enc-lastvet-imaging |
Operational |
| lastvet-edge | Caddy ingress (Cox static IP → API upstreams) | 110 | 192.168.1.89 |
2 vCPU / 4 GB / 50 GB | tank-fast |
Operational |
| observability | Platform metrics/logs (Prometheus, Grafana, Loki, Alertmanager) | 111 | 192.168.1.93 |
8 vCPU / 16 GB / 50 GB + 450 GB data | tank-fast |
Operational |
VMID column: Populate from Proxmox (qm list) before cutover. This document intentionally does not invent IDs.
Backups: Nightly vzdump of all VMs; primary offsite copy to Backblaze B2 (HIPAA-eligible BAA). LastVet VMs require encrypted backup streams and retention aligned to HIPAA once PHI is present.
Shared services¶
inference-01 (compute-only)¶
| Property | Value |
|---|---|
| Software | Ollama 0.32.6, NVIDIA T4 passthrough |
| Endpoint | http://192.168.1.40:11434 (LAN); Cloudflare Tunnel + Access where a product edge must reach inference (Angel Worker digest path) |
| Tenancy | Modelfile aliases per product; no shared chat memory; models loaded per alias |
| API contract | Native /api/chat, /api/embeddings, /api/tags only |
Alias inventory (current / planned):
| Alias | Tenant | Notes |
|---|---|---|
meridian-mistral-7b |
Meridian | Eval harness default |
sovereign-mistral-7b |
Sovereign | Odysseus local lane |
angel-mistral-7b |
Angel | Corpus rank + local batch |
lastvet-* |
LastVet | To provision before M1 model-serving on R940 |
Explicit non-goals on inference-01: Postgres, MCP hosts, product secrets, veteran PHI storage (LastVet inference runs only after Meridian eval gate and counsel-approved hosting posture).
Data sovereignty¶
Each tenant owns a dedicated data plane:
| Tenant | Database | Object / vector store | Reference implementation |
|---|---|---|---|
| Meridian | Postgres 16.14 + pgvector 0.6.0 on meridian-rag | Embeddings in pgvector; data dir /data/postgres-main |
Reference impl for platform pattern |
| Sovereign | Postgres + pgvector on sovereign-mem | MemPalace rehydrated from unicorn Chroma/SQLite into pgvector (see SOVEREIGN_ARCHITECTURE_V2.md) | App connects over TCP; no NFS |
| Angel (local) | Postgres + pgvector on angel-local | Experimental corpus indexes; production corpus rows stay in Neon (Cloudflare edge) | Hybrid; see ANGEL_ARCHITECTURE_V2.md |
| LastVet | Postgres 18 on lastvet-db (staging + prod VMs) | Imaging on lastvet-imaging (MinIO); legacy uploads on API VM ZFS (EFS parity) | LASTVET_MIGRATION_PLAN.md |
Prohibited: Shared Postgres instance, shared MinIO bucket across tenants, NFS/Chroma mounts between sovereign-app and sovereign-mem (previous deployment plan NFS option is retired in favor of Postgres-over-TCP).
Secrets architecture¶
Pattern (all R940 VMs):
/etc/bitwarden/access-token mode 440, root:ryan
/usr/local/bin/bws Bitwarden Secrets Manager CLI
/etc/profile.d/bws.sh exports BWS_ACCESS_TOKEN for interactive shells (optional)
systemd EnvironmentFile= loads token for services (preferred over profile.d for daemons)
ExecStart=... bws run --project-id <uuid> -- /path/to/service
Machine account: proxmox-machine service account; per-VM access tokens with read on relevant projects (angel, lastvet, proxmox, sovereign, meridian as scoped).
| Project | Consumers |
|---|---|
lastvet |
lastvet-api VMs, deploy scripts, iOS sync, R940 Tailscale VM auth key (lastvet-gates/bitwarden/secrets-manifest.json) |
meridian |
meridian-eval, meridian-rag |
sovereign |
sovereign-app, sovereign-mem |
angel |
angel-local; Cloudflare deploy pushes selected keys via wrangler (edge lane) |
proxmox |
Host-level backup credentials, B2 keys |
Rules:
- No production secrets in git.
detect-secretspre-commit hook on every repo. - Cloudflare Worker secrets for Angel/LastVet edges are pushed from Bitwarden at deploy time, not hand-entered in dashboard.
- AWS Secrets Manager (
lastvet-{env}/app,lastvet-{env}/rds/*) remains authoritative until LastVet cutover; then Bitwardenlastvetproject becomes authoritative on R940.
Network topology¶
Current state (August 2026)¶
| Layer | Detail |
|---|---|
| LAN | Flat 192.168.1.0/24 on Proxmox bridge |
| Admin | Tailscale mesh (tailc3bbdc.ts.net) on all nodes; passwordless SSH keys; passwordless sudo for ryan |
| Out-of-band | iDRAC on dedicated port (not bridged to production VLANs) |
| Hardware fault (Aug 8, 2026) | Integrated BCM5720 NIC fault (Dell SR 230104573, Blaine Tuesday). Production traffic uses Intel X710-T Port 1 (healthy). Integrated NIC uncabled until replaced. |
| Edge | LastVet API DNS grey-cloud to AWS ALB today; Angel/LastVet marketing on Cloudflare Pages |
Target VLAN plan¶
Segmentation replaces flat LAN before LastVet prod cutover. Exact Proxmox VLAN IDs to confirm on switch config.
| VLAN / segment | Intended tenants | Notes |
|---|---|---|
| 1 | iDRAC / OOB | Physical only |
| 10 | Proxmox host management | Hypervisor admin |
| 20 | Sovereign (sovereign-app, sovereign-mem) |
East-west: app → mem Postgres, app → inference-01 |
| 21 | Angel (angel-local) |
app → inference-01; optional cloudflared egress |
| 22 | Meridian (meridian-eval, meridian-rag) |
eval → rag Postgres; eval → inference-01 |
| 30 | Shared inference (inference-01) |
Allow 11434/tcp from 20, 21, 22, 40, 50 only |
| 40 | LastVet staging (lastvet-api, lastvet-db, lastvet-imaging) |
No route to VLAN 50 |
| 50 | LastVet production | No route to VLAN 40; stricter egress |
Tailscale: Admin overlay and inter-service naming layer (MagicDNS). See Inter-service naming. Not a substitute for VLAN isolation of LastVet staging vs prod.
Open question: Whether LastVet public ingress uses cloudflared, Tailscale Funnel/Serve, or WireGuard to VLAN 40/50 — decided in LASTVET_MIGRATION_PLAN.md.
Compute plane¶
┌─────────────────────────────────────────┐
│ Proxmox VE 8.4.20 (R940) │
│ X710-T Port 1 = production uplink │
└─────────────────────────────────────────┘
┌──────────────┬──────────────┬──────────────┬──────────────┐
│ VLAN 20–22 │ VLAN 30 │ VLAN 40/50 │ VLAN 10 │
│ Product VMs │ inference-01 │ LastVet VMs │ mgmt │
│ + MCP hosts │ Ollama + T4 │ (reserved) │ │
└──────┬───────┴──────┬───────┴──────┬───────┴──────────────┘
│ │ │
└──────────────┴──────────────┘
LAN / Tailscale
GPU workloads do not time-share across tenants at the Ollama layer beyond loaded models; scheduling is operational (pull aliases, monitor VRAM).
Storage plane¶
| Pool | Technology | Use |
|---|---|---|
| tank-fast | SSD mirrors (ZFS) | Latency-sensitive: Postgres data dirs, API VM root + upload cache, inference model store |
| tank-bulk | RAIDZ2 (ZFS) | Backups, imaging object bulk, long-retention audit log archives |
Per-VM isolation: Dedicated ZFS datasets (or separate virtual disks) per VM; no shared datasets mounted to multiple tenants.
Encryption: ZFS native encryption at rest for LastVet datasets (required before PHI). Document keys in Bitwarden proxmox project, not on disk plaintext.
Proxmox VM auto-boot and guest agent¶
Policy (August 2026): Every production VM on pve-r940 has onboot=1. After a host reboot or network disruption, VMs must return without manual qm start. VMs 107–110 previously defaulted to onboot=0 and did not auto-recover after August 2026 outages.
| VMID | Name | onboot |
startup order |
Notes |
|---|---|---|---|---|
| 100 | agent-01 | 1 | 2 | Automation host |
| 101 | inference-01 | 1 | 3 (up=60) |
GPU warm-up delay |
| 102 | meridian-eval | 1 | 4 | |
| 103 | meridian-rag | 1 | 5 | |
| 104 | sovereign-app | 1 | (default) | |
| 105 | sovereign-mem | 1 | (default) | |
| 106 | angel-local | 1 | (default) | |
| 108 | lastvet-db | 1 | 10 | Postgres must be up first |
| 107 | lastvet-api | 1 | 11 (up=15) |
Depends on lastvet-db |
| 109 | lastvet-imaging | 1 | 12 | Object store before edge routes traffic |
| 110 | lastvet-edge | 1 | 13 | Caddy backends need API + imaging reachable |
| 111 | observability | 1 | 14 (up=30) |
Platform metrics/logs; after LastVet stack |
LastVet startup ordering rationale: Lower startup order starts first. lastvet-db (108) before lastvet-api (107) so connection pools succeed on boot. lastvet-imaging (109) before lastvet-edge (110) so Caddy upstreams resolve. observability (111) starts after LastVet with a 30s delay so Phase 2 scrape targets exist. startup delay is not currently set on LastVet VMs; add up=N if race conditions appear in journal logs.
qemu-guest-agent: Required on every VM. Proxmox sets agent=1 on the VM config; the package must also run inside the guest (qemu-guest-agent systemd unit). The agent enables:
qm agent pinghealth checks from the host- Filesystem freeze during
vzdumpsnapshot mode (consistent backup without skipping fs-freeze) - Clean shutdown signals from the hypervisor
Install inside Ubuntu guests: apt install qemu-guest-agent && systemctl enable --now qemu-guest-agent. Verify from pve-r940: qm agent <VMID> ping (empty output = success).
VM provisioning (standard pattern)¶
Decision (August 2026): New Ubuntu 24.04 LTS VMs on pve-r940 use the official Noble cloud disk image, not the Proxmox ubuntu-24.04-standard_*.tar.zst template.
Why not the Proxmox .tar.zst template?¶
The Proxmox marketplace ubuntu-24.04-standard artifact is a root filesystem tree (directory tarball). Importing it with scsi0,...,import-from=... on a ZFS volume does not produce a bootable GPT disk (no partition table; first boot never configures network). Do not use import-from with that template for new VMs.
Standard image¶
| Property | Value |
|---|---|
| Image file | noble-server-cloudimg-amd64.img |
| Source | Ubuntu cloud images |
| Cache on host | /var/lib/vz/template/cache/noble-server-cloudimg-amd64.img |
| Import command | qm importdisk <VMID> <path-to-img> tank-fast |
| Attach | qm set <VMID> --scsi0 tank-fast:vm-<VMID>-disk-N,... then qm resize <VMID> scsi0 <size> |
| Cloud-init | Proxmox ide2 cloudinit drive: ciuser, sshkeys, ipconfig0, optional cicustom user snippet |
| Boot order | Always set qm set <VMID> --boot order=scsi0 before first start (empty boot order = silent failure) |
First-boot checklist: serial0=socket, vga=serial0, agent=enabled=1, static ipconfig0, both Ryan SSH keys in sshkeys file (not inline string), passwordless sudo via cloud-init or post-boot sudoers.d/ryan.
Reference implementation: VM 111 (observability, August 2026). See ../observability/OBSERVABILITY_STACK.md.
Tailscale VM onboarding¶
Decision (August 2026): Headless VM join uses a reusable pre-authorized auth key stored in Bitwarden, not interactive browser login during automation.
Bitwarden secret¶
| Key | Project | Purpose |
|---|---|---|
LASTVET_R940_TAILSCALE_AUTH_KEY |
lastvet |
Reusable Tailscale auth key for new R940 VMs |
Ryan generates the key in Tailscale admin → Settings → Keys. Cursor/automation reads from BWS; never commit or log the value.
| Key property | Value |
|---|---|
| Reusable | Yes |
| Preauthorized | Yes |
| Tag | tag:r940-vm |
| Expiration | 90 days (rotate on calendar; update BWS before expiry) |
ACL prerequisite¶
Create tag:r940-vm in the tailnet ACL before issuing the key. Example intent (exact ACL is operator-maintained in Tailscale admin):
Tag limits new nodes to R940-scoped access (no public funnel/serve; east-west admin mesh only). Review ACL whenever a new VM class is added.
Usage at provision time¶
TAILSCALE_AUTHKEY=$(bws secret get <id> -o json | jq -r '.value')
sudo tailscale up --hostname=<vm-hostname> --accept-dns=true --auth-key="${TAILSCALE_AUTHKEY}"
MagicDNS name follows VM hostname: <hostname>.tailc3bbdc.ts.net.
fail2ban (platform default)¶
Decision (August 2026): R940 VMs that expose SSH on the LAN run fail2ban with a shared ignore list for trusted admin paths.
Default /etc/fail2ban/jail.local¶
| Range | Why whitelisted |
|---|---|
127.0.0.1/8 |
Local health checks |
192.168.1.0/24 |
Flat LAN admin (agent-01, Proxmox host, VM-to-VM on LAN) |
100.64.0.0/10 |
Tailscale CGNAT (operator Mac, mesh nodes) |
Operational note: Failed SSH attempts from agent-01 during provisioning (wrong key before cloud-init settles) can trigger a ban if 192.168.1.0/24 is missing from ignoreip. Always include LAN + Tailscale on platform VMs.
Public SSH warning: Any VM with SSH reachable from public IP ranges must not add 0.0.0.0/0 or wide ignore ranges to fail2ban. Platform VMs use LAN + Tailscale SSH only; no Cox port-forward to VM SSH.
Admin UI access (Tailscale-only)¶
Decision (August 2026): Platform operator consoles (Grafana, Prometheus UI, Alertmanager UI) are Tailscale-only. No LAN or public exposure.
| Service | Example | ufw policy |
|---|---|---|
| Grafana | observability.tailc3bbdc.ts.net:3000 |
Allow 100.64.0.0/10 only |
| Prometheus | :9090 on observability VM |
Allow Tailscale CIDR only |
| Alertmanager | :9093 |
Allow Tailscale CIDR only |
| Loki push (Phase 3) | :3100 |
Tailscale + 192.168.1.0/24 (Promtail from other VMs) |
| SSH | :22 |
LAN 192.168.1.0/24 only |
Veteran-facing ingress (Caddy on lastvet-edge, Cox static IP) is a separate path and does not expose observability ports.
Backup and DR¶
| Tier | Mechanism | Retention |
|---|---|---|
| VM snapshot | Nightly Proxmox vzdump → tank-bulk |
Rolling nightly + weekly (confirm counts) |
| Offsite | Backblaze B2 (HIPAA-eligible BAA) | Encrypted backup streams |
| Second site | Second physical location | Planned as it materializes |
| LastVet | Same + extra rigor: encrypted vzdump, immutable B2 bucket policy, retention aligned to HIPAA audit (6+ years for audit logs, not necessarily full VM images) |
Recovery objective (honest): Single-host R940 is not HA. DR = restore VM from vzdump + Postgres PITR from WAL archives (LastVet DB VM must enable WAL archiving before prod PHI).
HA posture¶
| Today | Future (funding gate) |
|---|---|
| Single Proxmox node | Second R940 or equivalent |
| No automatic failover | Proxmox cluster + replicated storage (mechanism TBD: ZFS send/receive vs Ceph vs NAS) |
| Tailscale + backups mitigate operator error | Explicit RTO/RPO targets with counsel |
Named limitation: a host failure stops all tenants until restore completes. LastVet cutover accepts this for the pre-PHI window with AWS rollback net retained 30+ days (see migration plan).
Compliance envelope¶
Controls the platform provides today¶
| Control | Implementation |
|---|---|
| VM isolation | Proxmox KVM boundaries |
| Secrets hygiene | Bitwarden + bws + detect-secrets |
| Encrypted backups to B2 | vzdump encryption + BAA |
| Admin audit | SSH key-only; sudo logged |
| Inference data minimization | No PHI on inference-01 by policy |
| Network fault handling | Documented NIC failover to X710-T |
Required before LastVet PHI on R940¶
| Gap | Target state |
|---|---|
| Audit log retention (6+ years) | Application consent_audit_log + infrastructure logs on tank-bulk with B2 copy; parity with AWS compliance-logging module (~2192-day CloudWatch, ~2555-day S3) |
| Encrypted at rest documentation | ZFS dataset encryption + MinIO SSE for imaging; written key custody procedure |
| Physical security | R940 location access controls documented for HIPAA Security Rule §164.310 |
| Incident response runbook | Breach notification aligned to HIPAA + CARIN commitments (last.vet-web Terms §13.1 CARIN Code of Conduct) |
| BAA coverage | B2 for backups; any remaining SaaS that touches PHI-adjacent metadata; no Railway once VA prod access granted (Gate 0.5 invariant) |
| Meridian eval gate | Harness blocks model deploy without Suite A/B/C pass (MERIDIAN_EVAL_SPEC.md) |
| NVLSP privacy counsel | Ongoing outreach; infrastructure change notification for VA Case A/B (migration plan) |
CARIN Code of Conduct: LastVet has attested to CARIN Trust Framework principles (see last.vet-web compliance pages, Terms §13.1, and signed artifacts in ../compliance/). Platform migration must not weaken veteran-controlled sharing, audit visibility, or deletion commitments documented in privacy policy.
MCP integration surface¶
Model Context Protocol (MCP) is the integration layer between AI-driven products and external systems (calendar, GitHub, Slack, filesystem, Monday, Bitwarden, eventually VA APIs).
Platform rule: One MCP host per tenant, on that tenant's app VM.
| Component | Location | Pattern |
|---|---|---|
| MCP host process | Product app VM (e.g., sovereign-app, future lastvet-api) |
Long-lived supervisor; HTTP API for product code |
| MCP tool servers | Supervised subprocesses | Scoped tool list per product; no cross-tenant tools |
| Inference loop | Calls inference-01 /api/chat |
Decision loop stays native Ollama |
| Not in scope | Shared MCP host, Streamlit chatbot UI | Products expose their own UX (Sovereign /sov/, LastVet apps, Angel Workers) |
LastVet MCP host is future (Gate 2+ VA API tools); architecture reserves port/systemd pattern on lastvet-api VM only.
Migration horizon¶
| Track | Timeline | Dependency |
|---|---|---|
| LastVet AWS → R940 | ~1 month | Critical path; see LASTVET_MIGRATION_PLAN.md |
| Meridian eval operational | Before LastVet prod model requests | Hard gate; meridian-eval + pipeline hook |
| Sovereign unicorn → R940 | Parallel | Must not consume LastVet VLAN 40/50 provisioning window |
| Angel local lane | Parallel | Edge stays Cloudflare; see ANGEL_ARCHITECTURE_V2.md |
| AWS decommission | 30+ days after LastVet prod stable | Railway already mandated gone before VA prod PHI |
Open questions (platform)¶
- Confirm VMIDs and meridian-rag / agent-01 IPs in Proxmox; update tenant map.
- Final VLAN ID mapping on the physical switch (segments 1/10/20/21/22/30/40/50).
- HA funding gate triggers and storage replication choice.
AWS_ENVIRONMENT.md— cited as canonical AWS inventory; vendored at../lastvet/AWS_ENVIRONMENT.md. Confirm parity table against §14 before sign-off.- LastVet staging vs prod: separate VMs per component vs single VM with systemd instances (cost/complexity tradeoff).