[object Object]

← back to Tk11438 Postgres Migration

Record verified private Gracie socket migration

676734b717b2e05b807b7ed95372ccaffc4f6593 · 2026-09-11 13:28:45 -0700 · Steve Abrams

Files touched

Diff

commit 676734b717b2e05b807b7ed95372ccaffc4f6593
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Fri Sep 11 13:28:45 2026 -0700

    Record verified private Gracie socket migration
---
 .gitignore                                         |   2 +
 GRACIE-BATCH.md                                    |   5 +-
 README.md                                          |   7 +-
 verification/gracie-rollout/after.json             | 252 +++++++++++++++++
 verification/gracie-rollout/applied.json           |   6 +
 verification/gracie-rollout/baseline.json          | 231 ++++++++++++++++
 verification/gracie-rollout/config-applied.json    |   7 +
 verification/gracie-rollout/e2e-proof.json         |  57 ++++
 .../gracie-rollout/error-log-baseline.json         |   5 +
 verification/gracie-rollout/independent-check.cjs  |  22 ++
 .../gracie-rollout/independent-preflight.json      | 307 +++++++++++++++++++++
 .../independent-runtime-firstfailure.json          |  35 +++
 .../gracie-rollout/independent-runtime.json        | 260 +++++++++++++++++
 verification/gracie-rollout/monitor.json           | 252 +++++++++++++++++
 verification/gracie-rollout/mutation-started.json  |   5 +
 verification/gracie-rollout/observation.json       |  58 ++++
 verification/gracie-rollout/preparation.json       |   9 +
 verification/gracie-rollout/restart-requested.json |   5 +
 verification/gracie-rollout/rollout.cjs            |  79 ++++++
 verification/gracie-rollout/startup-schema.json    |  15 +
 verification/gracie-rollout/verification.json      |  58 ++++
 verification/gracie-rollout/verify-failure.json    |   6 +
 22 files changed, 1681 insertions(+), 2 deletions(-)

diff --git a/.gitignore b/.gitignore
index 8ea1807..dd8b0f0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,5 @@ build/
 __pycache__/
 
 /verification/ken-rollout/private/
+
+/verification/gracie-rollout/private/
diff --git a/GRACIE-BATCH.md b/GRACIE-BATCH.md
index 95a86f0..1f5d71e 100644
--- a/GRACIE-BATCH.md
+++ b/GRACIE-BATCH.md
@@ -1,6 +1,9 @@
+Status: APPLIED AND VERIFIED locally — source9661303. Do not repeat. Steve approved with private/nothing-online constraint; localhost bind added. Evidence verification/gracie-rollout/e2e-proof.json. No emails or publishing.
+
+Historical approved proposal follows:
 # TK-11438 — Gracie socket migration approval
 
-Status: PENDING. Source patches prepared; no changes applied.
+Status at proposal time: PENDING. Now applied; see completion above.
 Owner: codex-run-11438. Scope: local Mac gracie-internal only.
 
 Approve this exact next batch:
diff --git a/README.md b/README.md
index ee958fa..71fd652 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # TK-11438 PostgreSQL socket migration
 
-Status: PARTIAL. Two approved batches applied; full fleet remains incomplete.
+Status: PARTIAL. Three approved batches applied; full fleet remains incomplete.
 
 First batch: showroom and Pattern Design Lab source, runtime and durable configs
 migrated and independently reverified (15 checks; 3,201 products/1,694 designs).
@@ -27,3 +27,8 @@ outside the Ken approval. NEXT-BATCH.md retains its historical approved scope.
 Remaining inventory is now classified, with explicit unresolved/runtime gaps.
 See verification/fleet-classification/README.md and GRACIE-BATCH.md for the
 prepared next batch. No additional rollout has been applied.
+
+Gracie batch APPLIED/VERIFIED locally, source9661303: PostgreSQL sockets and
+127.0.0.1-only HTTP,150catalogitems preserved,auth+private-interface checks pass.
+Independent evidence and private rollback: verification/gracie-rollout/.
+No online publishing or emails. Overall fleet ticket remains incomplete.
diff --git a/verification/gracie-rollout/after.json b/verification/gracie-rollout/after.json
new file mode 100644
index 0000000..d37fe3d
--- /dev/null
+++ b/verification/gracie-rollout/after.json
@@ -0,0 +1,252 @@
+{
+  "at": "2026-09-11T20:14:49.860Z",
+  "pid": 91857,
+  "pm_id": 12,
+  "restarts": 2,
+  "controls": {
+    "auth_sha": "[stored in private rollback evidence]",
+    "PGHOST": null,
+    "nested_PGHOST": null,
+    "DATA_SOURCE": null,
+    "PORT": "10073",
+    "cwd": "/Users/macstudio3/Projects/gracie-internal",
+    "script": "/Users/macstudio3/Projects/gracie-internal/server.js"
+  },
+  "http": [
+    {
+      "route": "/healthz",
+      "auth": "missing",
+      "status": 200,
+      "body_sha": "4062edaf750fb8074e7e83e0c9028c94e32468a8b6f1614774328ef045150f93",
+      "bytes": 11
+    },
+    {
+      "route": "/healthz",
+      "auth": "invalid",
+      "status": 200,
+      "body_sha": "4062edaf750fb8074e7e83e0c9028c94e32468a8b6f1614774328ef045150f93",
+      "bytes": 11
+    },
+    {
+      "route": "/healthz",
+      "auth": "valid",
+      "status": 200,
+      "body_sha": "4062edaf750fb8074e7e83e0c9028c94e32468a8b6f1614774328ef045150f93",
+      "bytes": 11
+    },
+    {
+      "route": "/api/products",
+      "auth": "missing",
+      "status": 401,
+      "body_sha": "45cceda8377a0f8cfb7a5dc927ee1760c648406764291c2032cbadad6e8e44fb",
+      "bytes": 24
+    },
+    {
+      "route": "/api/products",
+      "auth": "invalid",
+      "status": 401,
+      "body_sha": "45cceda8377a0f8cfb7a5dc927ee1760c648406764291c2032cbadad6e8e44fb",
+      "bytes": 24
+    },
+    {
+      "route": "/api/products",
+      "auth": "valid",
+      "status": 200,
+      "body_sha": "b01acb69f4bd1d7d3c64d4dead18b84cf7f7026e9a702a2e9a77b08f66940264",
+      "bytes": 188603
+    },
+    {
+      "route": "/api/requests",
+      "auth": "missing",
+      "status": 401,
+      "body_sha": "45cceda8377a0f8cfb7a5dc927ee1760c648406764291c2032cbadad6e8e44fb",
+      "bytes": 24
+    },
+    {
+      "route": "/api/requests",
+      "auth": "invalid",
+      "status": 401,
+      "body_sha": "45cceda8377a0f8cfb7a5dc927ee1760c648406764291c2032cbadad6e8e44fb",
+      "bytes": 24
+    },
+    {
+      "route": "/api/requests",
+      "auth": "valid",
+      "status": 200,
+      "body_sha": "4682017fdbc8ce5539bc7e44ef687440bfae054688ac409c289284cde01204c6",
+      "bytes": 197
+    }
+  ],
+  "product_count": 150,
+  "vendor": {
+    "identity": {
+      "database": "dw_unified",
+      "role": "dw_admin",
+      "addr": null,
+      "readonly": "on",
+      "database_oid": 16391,
+      "server_started": "2026-09-09T15:05:54.745Z"
+    },
+    "requests": {
+      "count": 1,
+      "last_id": "7"
+    },
+    "schema": [
+      {
+        "column_name": "id",
+        "data_type": "bigint",
+        "is_nullable": "NO",
+        "column_default": "nextval('vendor_requests_id_seq'::regclass)"
+      },
+      {
+        "column_name": "req_no",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "req_type",
+        "data_type": "text",
+        "is_nullable": "NO",
+        "column_default": null
+      },
+      {
+        "column_name": "vendor_code",
+        "data_type": "text",
+        "is_nullable": "NO",
+        "column_default": null
+      },
+      {
+        "column_name": "vendor_name",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "vendor_email",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "account_number",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "dw_sku",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "mfr_sku",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "product_title",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "qty",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "note",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "requested_by",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "status",
+        "data_type": "text",
+        "is_nullable": "NO",
+        "column_default": "'open'::text"
+      },
+      {
+        "column_name": "email_subject",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "email_body",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "email_message_id",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "created_at",
+        "data_type": "timestamp with time zone",
+        "is_nullable": "NO",
+        "column_default": "now()"
+      },
+      {
+        "column_name": "sent_at",
+        "data_type": "timestamp with time zone",
+        "is_nullable": "YES",
+        "column_default": null
+      }
+    ],
+    "indexes": [
+      {
+        "indexname": "idx_vendor_requests_vendor",
+        "indexdef": "CREATE INDEX idx_vendor_requests_vendor ON public.vendor_requests USING btree (vendor_code, created_at DESC)"
+      },
+      {
+        "indexname": "vendor_requests_pkey",
+        "indexdef": "CREATE UNIQUE INDEX vendor_requests_pkey ON public.vendor_requests USING btree (id)"
+      },
+      {
+        "indexname": "vendor_requests_req_no_key",
+        "indexdef": "CREATE UNIQUE INDEX vendor_requests_req_no_key ON public.vendor_requests USING btree (req_no)"
+      },
+      {
+        "indexname": "vendor_requests_vendor_code_id_idx",
+        "indexdef": "CREATE INDEX vendor_requests_vendor_code_id_idx ON public.vendor_requests USING btree (vendor_code, id DESC)"
+      }
+    ]
+  },
+  "catalog": {
+    "database": "dw_unified",
+    "role": "macstudio3",
+    "addr": null,
+    "readonly": "on"
+  },
+  "vendor_config": {
+    "host": "/tmp",
+    "database": "dw_unified",
+    "user": "dw_admin",
+    "port": 5432
+  },
+  "saved_match": true,
+  "listeners": [
+    "node    91857 macstudio3   15u  IPv4 0x31f9c8265db2c7e5      0t0  TCP 127.0.0.1:10073 (LISTEN)"
+  ],
+  "database_tcp": [],
+  "source_hashes": {
+    "server": "d577f28fe6b305bfad4ba29c5a00fbbf896ec963f016546e4873e7ca57a2ba21",
+    "vendor": "d87ab5d2e4d44953aea64befe63c033dc0bc8479c3bc11fc5328c7bfb6d8690e"
+  },
+  "bundle_sha": "764cfa9e2ac274c272c04326ffda8856eda425c721555edbc875bf31e5d9c5d6",
+  "email_sends": 0
+}
diff --git a/verification/gracie-rollout/applied.json b/verification/gracie-rollout/applied.json
new file mode 100644
index 0000000..cb665ab
--- /dev/null
+++ b/verification/gracie-rollout/applied.json
@@ -0,0 +1,6 @@
+{
+  "at": "2026-09-11T20:14:17.961Z",
+  "verdict": "APPLIED_VERIFY_PENDING",
+  "pid": 91857,
+  "previous_pid": 8186
+}
diff --git a/verification/gracie-rollout/baseline.json b/verification/gracie-rollout/baseline.json
new file mode 100644
index 0000000..c8c951c
--- /dev/null
+++ b/verification/gracie-rollout/baseline.json
@@ -0,0 +1,231 @@
+{
+  "at": "2026-09-11T20:12:30.687Z",
+  "pid": 8186,
+  "pm_id": 12,
+  "restarts": 1,
+  "controls": {
+    "auth_sha": "[stored in private rollback evidence]",
+    "PGHOST": null,
+    "nested_PGHOST": null,
+    "DATA_SOURCE": null,
+    "PORT": "10073",
+    "cwd": "/Users/macstudio3/Projects/gracie-internal",
+    "script": "/Users/macstudio3/Projects/gracie-internal/server.js"
+  },
+  "http": [
+    {
+      "route": "/healthz",
+      "auth": "missing",
+      "status": 200,
+      "body_sha": "4062edaf750fb8074e7e83e0c9028c94e32468a8b6f1614774328ef045150f93",
+      "bytes": 11
+    },
+    {
+      "route": "/healthz",
+      "auth": "invalid",
+      "status": 200,
+      "body_sha": "4062edaf750fb8074e7e83e0c9028c94e32468a8b6f1614774328ef045150f93",
+      "bytes": 11
+    },
+    {
+      "route": "/healthz",
+      "auth": "valid",
+      "status": 200,
+      "body_sha": "4062edaf750fb8074e7e83e0c9028c94e32468a8b6f1614774328ef045150f93",
+      "bytes": 11
+    },
+    {
+      "route": "/api/products",
+      "auth": "missing",
+      "status": 401,
+      "body_sha": "45cceda8377a0f8cfb7a5dc927ee1760c648406764291c2032cbadad6e8e44fb",
+      "bytes": 24
+    },
+    {
+      "route": "/api/products",
+      "auth": "invalid",
+      "status": 401,
+      "body_sha": "45cceda8377a0f8cfb7a5dc927ee1760c648406764291c2032cbadad6e8e44fb",
+      "bytes": 24
+    },
+    {
+      "route": "/api/products",
+      "auth": "valid",
+      "status": 200,
+      "body_sha": "b01acb69f4bd1d7d3c64d4dead18b84cf7f7026e9a702a2e9a77b08f66940264",
+      "bytes": 188603
+    }
+  ],
+  "product_count": 150,
+  "vendor": {
+    "identity": {
+      "database": "dw_unified",
+      "role": "dw_admin",
+      "addr": "127.0.0.1/32",
+      "readonly": "on",
+      "database_oid": 16391,
+      "server_started": "2026-09-09T15:05:54.745Z"
+    },
+    "requests": {
+      "count": 1,
+      "last_id": "7"
+    },
+    "schema": [
+      {
+        "column_name": "id",
+        "data_type": "bigint",
+        "is_nullable": "NO",
+        "column_default": "nextval('vendor_requests_id_seq'::regclass)"
+      },
+      {
+        "column_name": "req_no",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "req_type",
+        "data_type": "text",
+        "is_nullable": "NO",
+        "column_default": null
+      },
+      {
+        "column_name": "vendor_code",
+        "data_type": "text",
+        "is_nullable": "NO",
+        "column_default": null
+      },
+      {
+        "column_name": "vendor_name",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "vendor_email",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "account_number",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "dw_sku",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "mfr_sku",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "product_title",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "qty",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "note",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "requested_by",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "status",
+        "data_type": "text",
+        "is_nullable": "NO",
+        "column_default": "'open'::text"
+      },
+      {
+        "column_name": "email_subject",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "email_body",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "email_message_id",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "created_at",
+        "data_type": "timestamp with time zone",
+        "is_nullable": "NO",
+        "column_default": "now()"
+      },
+      {
+        "column_name": "sent_at",
+        "data_type": "timestamp with time zone",
+        "is_nullable": "YES",
+        "column_default": null
+      }
+    ],
+    "indexes": [
+      {
+        "indexname": "idx_vendor_requests_vendor",
+        "indexdef": "CREATE INDEX idx_vendor_requests_vendor ON public.vendor_requests USING btree (vendor_code, created_at DESC)"
+      },
+      {
+        "indexname": "vendor_requests_pkey",
+        "indexdef": "CREATE UNIQUE INDEX vendor_requests_pkey ON public.vendor_requests USING btree (id)"
+      },
+      {
+        "indexname": "vendor_requests_req_no_key",
+        "indexdef": "CREATE UNIQUE INDEX vendor_requests_req_no_key ON public.vendor_requests USING btree (req_no)"
+      },
+      {
+        "indexname": "vendor_requests_vendor_code_id_idx",
+        "indexdef": "CREATE INDEX vendor_requests_vendor_code_id_idx ON public.vendor_requests USING btree (vendor_code, id DESC)"
+      }
+    ]
+  },
+  "catalog": {
+    "database": "dw_unified",
+    "role": "macstudio3",
+    "addr": "::1/128",
+    "readonly": "on"
+  },
+  "vendor_config": {
+    "host": "127.0.0.1",
+    "database": "dw_unified",
+    "user": "dw_admin",
+    "port": 5432
+  },
+  "saved_match": true,
+  "listeners": [
+    "node    8186 macstudio3   15u  IPv6 0x643c6ef75a2b5d71      0t0  TCP *:10073 (LISTEN)"
+  ],
+  "database_tcp": [],
+  "source_hashes": {
+    "server": "b6a0dee64b777d1e3c41f806d93f51e44d803d3f8f300f0cc245cb75edf5406e",
+    "vendor": "ce0099389bf08e01e2a7a08f2a1bf442e146cd0ea17500abd583bb93af840702"
+  },
+  "bundle_sha": "764cfa9e2ac274c272c04326ffda8856eda425c721555edbc875bf31e5d9c5d6",
+  "email_sends": 0
+}
diff --git a/verification/gracie-rollout/config-applied.json b/verification/gracie-rollout/config-applied.json
new file mode 100644
index 0000000..a1c4865
--- /dev/null
+++ b/verification/gracie-rollout/config-applied.json
@@ -0,0 +1,7 @@
+{
+  "at": "2026-09-11T20:14:16.207Z",
+  "dump": {
+    "only_gracie_two_fields": true
+  },
+  "privacy": "127.0.0.1 listener in source"
+}
diff --git a/verification/gracie-rollout/e2e-proof.json b/verification/gracie-rollout/e2e-proof.json
new file mode 100644
index 0000000..61e79cf
--- /dev/null
+++ b/verification/gracie-rollout/e2e-proof.json
@@ -0,0 +1,57 @@
+{
+  "ticket": "TK-11438",
+  "risk_tier": "R4",
+  "at": "2026-09-11T20:23:47.192Z",
+  "verdict": "PASS Gracie batch; overall fleet ticket incomplete",
+  "source_commit": "966130377ec694055a0688d0e1bd7f4bdf454a93",
+  "approval": "Steve explicitly approved Gracie batch and required private/nothing online; local-only implementation, no emails",
+  "intent": "Move Gracie PostgreSQL connections to Unix sockets while preserving catalog/auth/schema and enforcing localhost-only HTTP",
+  "baseline": {
+    "pid": 8186,
+    "listener": "*:10073",
+    "products": 150,
+    "transport": "TCP",
+    "schema": "existing vendor_requests"
+  },
+  "boundaries": {
+    "source": "two files,three changed lines",
+    "service": "one restart; PID91857 stable/restarts2",
+    "data": "catalog150; Gracie request records and schema/index definitions unchanged",
+    "database": "catalog macstudio3 and vendor dw_admin roles preserved on dw_unified; socket identity and missingENOENT",
+    "http": "health200 and protected catalog/requests401/401/200",
+    "privacy": "127.0.0.1 listener only;8nonloopbackIPv4 probes fail includingLAN/Tailscale;17localproxy/tunnel configs show no route"
+  },
+  "negative_checks": [
+    "missing/invalid authentication401",
+    "nonloopback connections fail",
+    "missing socketENOENT",
+    "peer edits rejected by rollback"
+  ],
+  "evidence": [
+    "baseline.json",
+    "after.json",
+    "startup-schema.json",
+    "verification.json",
+    "observation.json",
+    "independent-preflight.json",
+    "independent-runtime.json"
+  ],
+  "independent_assertions": 22,
+  "rollback": {
+    "status": "rehearsed,not invoked live",
+    "private_backups": "private/",
+    "file_mode": "0600",
+    "directory_mode": "0700",
+    "privacy": "restores transport while retaininglocalhost bind"
+  },
+  "limits": [
+    "Cloud-managed and remote proxy routes not audited; no online publication performed",
+    "Catalog is served from unchangedJSONL; configured catalogDB connection independently tested",
+    "Initial verifier Date/string mismatch retained; fixed test, no repeat restart",
+    "Remaining original/expandedfleet and scheduler migration not complete"
+  ],
+  "email_sends": 0,
+  "remote_pushes": 0,
+  "deployments": 0,
+  "tcp_shutdown": false
+}
diff --git a/verification/gracie-rollout/error-log-baseline.json b/verification/gracie-rollout/error-log-baseline.json
new file mode 100644
index 0000000..4ac6d76
--- /dev/null
+++ b/verification/gracie-rollout/error-log-baseline.json
@@ -0,0 +1,5 @@
+{
+  "at": "2026-09-11T20:14:16.207Z",
+  "path": "/Users/macstudio3/.pm2/logs/gracie-internal-error.log",
+  "size": 0
+}
diff --git a/verification/gracie-rollout/independent-check.cjs b/verification/gracie-rollout/independent-check.cjs
new file mode 100644
index 0000000..67da1de
--- /dev/null
+++ b/verification/gracie-rollout/independent-check.cjs
@@ -0,0 +1,22 @@
+const fs=require('fs'),cp=require('child_process'),A=require('assert/strict'),C=require('crypto'),os=require('os'),net=require('net');
+const D='/Users/macstudio3/Projects/gracie-internal',O=__dirname,dep='/Users/macstudio3/.npm-global/lib/node_modules/pm2/node_modules/';
+const {Client}=require(D+'/node_modules/pg'),axon=require(dep+'pm2-axon'),rpc=require(dep+'pm2-axon-rpc');
+const read=p=>fs.readFileSync(p),j=p=>JSON.parse(read(p)),sha=b=>C.createHash('sha256').update(b).digest('hex'),run=(c,a)=>cp.execFileSync(c,a,{encoding:'utf8',timeout:15000,maxBuffer:8e6});
+const proof={task:'TK-11438',owner:'codex-run-11438-verifier',at:new Date().toISOString(),checks:[],application_mutations:0,email_sends:0};
+const ok=(name,data=true)=>proof.checks.push({name,verdict:'PASS',data});
+function monitor(){return new Promise((r,q)=>{const s=axon.socket('req'),c=new rpc.Client(s),t=setTimeout(()=>{s.close();q(Error('monitor timeout'));},30000);s.on('error',e=>{clearTimeout(t);s.close();q(e);});s.connect('/Users/macstudio3/.pm2/rpc.sock');c.call('getMonitorData',{},(e,x)=>{clearTimeout(t);s.close();e?q(Error('monitor failed')):r(x);});});}
+async function db(o,f){const c=new Client({...o,application_name:'TK11438-Gracie-independent',connectionTimeoutMillis:3000,options:'-c default_transaction_read_only=on -c statement_timeout=5000'});try{await c.connect();return await f(c);}finally{await c.end().catch(()=>{});}}
+function probe(host){return new Promise(r=>{const s=net.createConnection({host,port:10073});s.setTimeout(3000);s.on('connect',()=>{s.destroy();r({host,connected:true});});s.on('error',e=>{s.destroy();r({host,connected:false,code:e.code});});s.on('timeout',()=>{s.destroy();r({host,connected:false,code:'TIMEOUT'});});});}
+(async()=>{
+const b=j(O+'/private/baseline.runtime.json'),rec=j(O+'/private/receipt.json');A.equal(j(O+'/startup-schema.json').verdict,'PASS');const matches=(await monitor()).filter(x=>x.name==='gracie-internal');A.equal(matches.length,1);const p=matches[0],e=p.pm2_env;proof.pid=p.pid;A.equal(e.pm_cwd,D);A.equal(e.pm_exec_path,D+'/server.js');A.equal(e.status,'online');A.equal(e.restart_time,b.restarts+1);A.notEqual(p.pid,b.pid);ok('Exact Gracie online after one restart',{pid:p.pid,restarts:e.restart_time});
+const saved=j('/Users/macstudio3/.pm2/dump.pm2').filter(x=>x.name==='gracie-internal');A.equal(saved.length,1);A.equal(saved[0].pm_cwd,D);A.equal(saved[0].pm_exec_path,D+'/server.js');for(const f of [e.PG,e.env.PG,saved[0].PG,saved[0].env.PG])A.equal(f,rec.next.PG);A.equal(new URL(e.PG).searchParams.get('host'),'/tmp');A(!e.PGHOST&&!e.env.PGHOST&&!saved[0].PGHOST&&!saved[0].env.PGHOST);A.equal(sha(e.BASIC_AUTH||''),b.controls.auth_sha);A.equal(e.DATA_SOURCE||null,b.controls.DATA_SOURCE);A.equal(String(e.PORT||10073),b.controls.PORT);ok('Effective/saved socket fields and unchanged auth/data/port controls');
+for(const s of rec.specs){A.equal(sha(read(s.path)),s.after_sha);A.equal(sha(read(O+'/private/privacy-rehearsal-'+s.key)),s.recovery_sha);}const server=read(D+'/server.js').toString(),vendor=read(D+'/lib/vendor-requests.js').toString();A(server.includes("app.listen(PORT, '127.0.0.1', () =>"));A(vendor.includes("host: process.env.PGHOST || (process.platform === 'darwin' ? '/tmp' : '127.0.0.1')"));A.equal(sha(read(D+'/data/gracie.jsonl')),b.bundle_sha);ok('Reviewed source hashes, privacy rollback copies and catalog bundle');
+const tcp=run('lsof',['-nP','-a','-p',String(p.pid),'-iTCP']),listeners=tcp.split('\n').filter(x=>x.includes('(LISTEN)'));A.equal(listeners.length,1);A(/127\.0\.0\.1:10073\s+\(LISTEN\)/.test(listeners[0]));A(!/:5432\b/.test(tcp));ok('Only 127.0.0.1:10073 listener and no TCP5432',listeners);
+const addresses=[...new Set(Object.values(os.networkInterfaces()).flat().filter(x=>x.family==='IPv4'&&!x.internal).map(x=>x.address)),'::1'];A(addresses.length>1);const blocked=[];for(const a of addresses){const r=await probe(a);A.equal(r.connected,false);A(['ECONNREFUSED','EHOSTUNREACH','ENETUNREACH','TIMEOUT'].includes(r.code));blocked.push(r);}ok('All nonloopback IPv4 plus IPv6 loopback reject 10073',blocked);
+const auth=e.BASIC_AUTH||server.match(/process\.env\.BASIC_AUTH \|\| '([^']+)'/)[1];for(const route of ['/healthz','/api/products','/api/requests'])for(const mode of ['missing','invalid','valid']){const headers=mode==='missing'?{}:{authorization:'Basic '+Buffer.from(mode==='valid'?auth:'TK11438:invalid').toString('base64')};const r=await fetch('http://127.0.0.1:10073'+route,{headers,signal:AbortSignal.timeout(8000)}),body=await r.text();A.equal(r.status,route==='/healthz'||mode==='valid'?200:401);if(route==='/healthz')A.deepEqual(JSON.parse(body),{ok:true});if(mode==='valid'&&route==='/api/products'){A.equal(JSON.parse(body).count,b.product_count);A.equal(sha(body),b.http.find(x=>x.route===route&&x.auth==='valid').body_sha);}if(mode==='valid'&&route==='/api/requests')A.equal(JSON.parse(body).requests.length,b.vendor.requests.count);ok(route+' '+mode,{status:r.status,body_sha256:sha(body),bytes:Buffer.byteLength(body)});}
+const secret=read('/Users/macstudio3/Projects/secrets-manager/.env').toString().match(/^DW_ADMIN_DB_PASSWORD=(.+)$/m),password=e.DW_ADMIN_DB_PASSWORD||(secret?secret[1].replace(/^["']|["']$/g,'').trim():'');const opts={host:'/tmp',port:5432,user:'dw_admin',database:'dw_unified',password};
+const v=await db(opts,async c=>({identity:(await c.query("SELECT current_database() database,current_user role,inet_client_addr()::text addr,current_setting('transaction_read_only') readonly,(SELECT oid FROM pg_database WHERE datname=current_database()) database_oid,pg_postmaster_start_time() server_started")).rows[0],requests:(await c.query("SELECT count(*)::int count,max(id)::text last_id FROM vendor_requests WHERE vendor_code='gracie'")).rows[0],schema:(await c.query("SELECT column_name,data_type,is_nullable,column_default FROM information_schema.columns WHERE table_schema='public' AND table_name='vendor_requests' ORDER BY ordinal_position")).rows,indexes:(await c.query("SELECT indexname,indexdef FROM pg_indexes WHERE schemaname='public' AND tablename='vendor_requests' ORDER BY indexname")).rows}));A.equal(v.identity.addr,null);A.equal(v.identity.readonly,'on');for(const k of ['database','role','database_oid'])A.equal(v.identity[k],b.vendor.identity[k]);A.equal(v.identity.server_started.toISOString(),b.vendor.identity.server_started);A.deepEqual(v.requests,b.vendor.requests);A.deepEqual(v.schema,b.vendor.schema);A.deepEqual(v.indexes,b.vendor.indexes);ok('Vendor socket identity and unchanged records/schema/indexes',{identity:v.identity,requests:v.requests});
+for(const [name,url]of [['effective',e.PG],['saved',saved[0].PG]]){const id=await db({connectionString:url},async c=>(await c.query("SELECT current_database() database,current_user role,inet_client_addr()::text addr,current_setting('transaction_read_only') readonly")).rows[0]);A.equal(id.addr,null);A.equal(id.readonly,'on');A.equal(id.database,b.catalog.database);A.equal(id.role,b.catalog.role);ok('Catalog '+name+' socket identity',id);}
+for(const [name,o]of [['vendor',{...opts,host:O+'/missing-socket'}],['catalog',{connectionString:(()=>{const u=new URL(e.PG);u.searchParams.set('host',O+'/missing-socket');return u.toString();})()}]]){let code;try{await db(o,async()=>{});}catch(e){code=e.code;}A.equal(code,'ENOENT');ok(name+' missing socket fails closed',code);}
+const unix=run('lsof',['-nP','-a','-p',String(p.pid),'-U']);A(/unix/.test(unix));ok('Gracie owns Unix sockets',{sha256:sha(unix),rows:unix.trim().split('\n').length-1});const last=(await monitor()).find(x=>x.name==='gracie-internal');A.equal(last.pid,p.pid);A.equal(last.pm2_env.restart_time,e.restart_time);ok('Process stable throughout verification');proof.commit=run('git',['-C',D,'rev-parse','HEAD']).trim();const diff=run('git',['-C',D,'show','--format=','--numstat','HEAD']).trim();A.equal(diff,'1\t1\tlib/vendor-requests.js\n2\t2\tserver.js');ok('Commit changes exactly three lines across two scoped files',{commit:proof.commit,numstat:diff});proof.verdict='PASS';proof.status='complete_scoped_verification';proof.scope_limits=['17 local proxy configs and 4 running proxy/tunnel processes inspected before rollout; remote/cloud-managed routes unqueried','Catalog currently uses unchanged JSONL; configured PG URI independently connected','Only GET routes after confirmed startup DDL; no POST or emails'];proof.commands=['Direct existing PM2 monitor RPC before/after','lsof process TCP/Unix','TCP connect all nonloopback IPv4 and ::1','9 loopback GET auth checks','Read-only PostgreSQL identity/count/schema/index queries','Source/rollback-copy/catalog bundle SHA256','git rev-parse and show --numstat'];
+})().catch(e=>{proof.verdict='FAIL';proof.status='partial';proof.error={name:e.name,code:e.code,message:String(e.message).replace(/postgres(?:ql)?:\/\/\S+/g,'[REDACTED_URI]')};}).finally(()=>{fs.writeFileSync(O+'/independent-runtime.json',JSON.stringify(proof,null,2)+'\n');console.log(JSON.stringify(proof,null,2));if(proof.verdict!=='PASS')process.exitCode=1;});
diff --git a/verification/gracie-rollout/independent-preflight.json b/verification/gracie-rollout/independent-preflight.json
new file mode 100644
index 0000000..c0e7955
--- /dev/null
+++ b/verification/gracie-rollout/independent-preflight.json
@@ -0,0 +1,307 @@
+{
+  "task": "TK-11438",
+  "at": "2026-09-11T20:12:25.834608+00:00",
+  "scope": "Gracie local privacy and startup static review",
+  "source_sha256": {
+    "/Users/macstudio3/Projects/gracie-internal/server.js": "b6a0dee64b777d1e3c41f806d93f51e44d803d3f8f300f0cc245cb75edf5406e",
+    "/Users/macstudio3/Projects/gracie-internal/lib/vendor-requests.js": "ce0099389bf08e01e2a7a08f2a1bf442e146cd0ea17500abd583bb93af840702"
+  },
+  "startup_email_path": false,
+  "startup_ddl": true,
+  "requests_get_before_apply": false,
+  "local_configs": [
+    {
+      "path": "/opt/homebrew/etc/nginx/fastcgi_params",
+      "sha256": "f37852d0113de30fa6bfc3d9b180ef99383c06739530dd482a8538503afd5a58",
+      "gracie_or_port_match": false,
+      "directives": []
+    },
+    {
+      "path": "/opt/homebrew/etc/nginx/scgi_params",
+      "sha256": "f27b2027c571ccafcfb0fbb3f54d7aeee11a984e3a0f5a1fdf14629030fc9011",
+      "gracie_or_port_match": false,
+      "directives": []
+    },
+    {
+      "path": "/opt/homebrew/etc/nginx/fastcgi.conf",
+      "sha256": "b2c3d480a58f61f3a7dc61850b461e892e36f236317765a4f2f6d558c928fa57",
+      "gracie_or_port_match": false,
+      "directives": []
+    },
+    {
+      "path": "/opt/homebrew/etc/nginx/uwsgi_params",
+      "sha256": "015cb581c2eb84b1a1ac9b575521d5881f791f632bfa62f34b26ba97d70c0d4f",
+      "gracie_or_port_match": false,
+      "directives": []
+    },
+    {
+      "path": "/opt/homebrew/etc/nginx/koi-win",
+      "sha256": "de518a9eafe86c8bc705e296d0ef26135835b46bdc0de01d1d50a630fa5d341e",
+      "gracie_or_port_match": false,
+      "directives": []
+    },
+    {
+      "path": "/opt/homebrew/etc/nginx/mime.types",
+      "sha256": "6f95d1d7d75e3c072907d845622a69d23110d1266c16ff122b3109b8b21f3ae9",
+      "gracie_or_port_match": false,
+      "directives": []
+    },
+    {
+      "path": "/opt/homebrew/etc/nginx/koi-utf",
+      "sha256": "b5f8a6d411db5e5d11d151d50cd1e962444732593adec0e1ef0a8c6eebec63ee",
+      "gracie_or_port_match": false,
+      "directives": []
+    },
+    {
+      "path": "/opt/homebrew/etc/nginx/win-utf",
+      "sha256": "0f221e54163907249b5397cb7357a4a9c946907ed4839c262dd09d8c9f9ca185",
+      "gracie_or_port_match": false,
+      "directives": []
+    },
+    {
+      "path": "/opt/homebrew/etc/nginx/nginx.conf",
+      "sha256": "fe6ba480238ac9d0f347bee06704b81b75d133a948caf61d083e5e744329e4bf",
+      "gracie_or_port_match": false,
+      "directives": [
+        {
+          "line": 18,
+          "text": "include       mime.types;"
+        },
+        {
+          "line": 36,
+          "text": "listen       8080;"
+        },
+        {
+          "line": 114,
+          "text": "include servers/*;"
+        }
+      ]
+    },
+    {
+      "path": "/Users/macstudio3/.cloudflared/ig-board.yml",
+      "sha256": "5a8a0ae5bc45dbde0569ba7d500e5928b8e61b6d6be070dd1c69db9f4f2f8de8",
+      "gracie_or_port_match": false,
+      "directives": [
+        {
+          "line": 5,
+          "text": "service: http://100.82.17.107:9810"
+        }
+      ]
+    },
+    {
+      "path": "/Users/macstudio3/.cloudflared/subfinder.yml",
+      "sha256": "ce811493cfd35d5277d4c2d2c4eaea0a41c80eff89f537df4cb4929fc1c7ccae",
+      "gracie_or_port_match": false,
+      "directives": [
+        {
+          "line": 5,
+          "text": "service: http://127.0.0.1:9948"
+        }
+      ]
+    },
+    {
+      "path": "/Users/macstudio3/.cloudflared/liveskus.yml",
+      "sha256": "a30c9d8acfacbbd2ecaf3abe3ab63fa379a4885dab7fc5efe2e4d953cbbc463a",
+      "gracie_or_port_match": false,
+      "directives": [
+        {
+          "line": 5,
+          "text": "service: http://127.0.0.1:9797"
+        }
+      ]
+    },
+    {
+      "path": "/Users/macstudio3/.cloudflared/buildingpermits.yml",
+      "sha256": "aa47da9b5e71cab0bb1042e1a41be80d8adbc8995d111891e0288f16467805ea",
+      "gracie_or_port_match": false,
+      "directives": [
+        {
+          "line": 5,
+          "text": "service: http://127.0.0.1:9873"
+        }
+      ]
+    },
+    {
+      "path": "/Users/macstudio3/.cloudflared/gated.yml",
+      "sha256": "f1bc8825dbafc80305c9dc8f9c55f162bbddc2a10f27eef76a2a009e93870078",
+      "gracie_or_port_match": false,
+      "directives": [
+        {
+          "line": 5,
+          "text": "service: http://127.0.0.1:9801"
+        }
+      ]
+    },
+    {
+      "path": "/Users/macstudio3/.cloudflared/tickets.yml",
+      "sha256": "7fff95a4568cfe8b2abf0a0933ffa318ccc8d8df6ad23a725064dee1ead713f8",
+      "gracie_or_port_match": false,
+      "directives": [
+        {
+          "line": 5,
+          "text": "service: http://127.0.0.1:9794"
+        }
+      ]
+    },
+    {
+      "path": "/Users/macstudio3/.cloudflared/exo.yml",
+      "sha256": "87dbb352dcb4336b6b3a22393d58cc87e2d1aa1636c7d975bbb69addced52adf",
+      "gracie_or_port_match": false,
+      "directives": [
+        {
+          "line": 5,
+          "text": "service: http://127.0.0.1:52415"
+        }
+      ]
+    },
+    {
+      "path": "/Users/macstudio3/.cloudflared/followup2.yml",
+      "sha256": "2b66d81e9476648bd96436e7ac26b93413952ca3b34fd6e72aa2c02386a73705",
+      "gracie_or_port_match": false,
+      "directives": [
+        {
+          "line": 5,
+          "text": "service: http://127.0.0.1:3737"
+        },
+        {
+          "line": 7,
+          "text": "service: http://127.0.0.1:9820"
+        },
+        {
+          "line": 9,
+          "text": "service: http://127.0.0.1:9791"
+        },
+        {
+          "line": 11,
+          "text": "service: http://127.0.0.1:9768"
+        },
+        {
+          "line": 13,
+          "text": "service: http://127.0.0.1:9768"
+        },
+        {
+          "line": 15,
+          "text": "service: http://127.0.0.1:4901"
+        },
+        {
+          "line": 17,
+          "text": "service: http://127.0.0.1:4902"
+        },
+        {
+          "line": 19,
+          "text": "service: http://127.0.0.1:4903"
+        },
+        {
+          "line": 21,
+          "text": "service: http://127.0.0.1:4904"
+        },
+        {
+          "line": 23,
+          "text": "service: http://127.0.0.1:4905"
+        },
+        {
+          "line": 25,
+          "text": "service: http://127.0.0.1:4906"
+        },
+        {
+          "line": 27,
+          "text": "service: http://127.0.0.1:9758"
+        },
+        {
+          "line": 29,
+          "text": "service: http://127.0.0.1:9792"
+        },
+        {
+          "line": 31,
+          "text": "service: http://127.0.0.1:9795"
+        },
+        {
+          "line": 33,
+          "text": "service: http://127.0.0.1:9794"
+        },
+        {
+          "line": 35,
+          "text": "service: http://127.0.0.1:9821"
+        },
+        {
+          "line": 37,
+          "text": "service: http://127.0.0.1:9915"
+        },
+        {
+          "line": 39,
+          "text": "service: http://127.0.0.1:9790"
+        },
+        {
+          "line": 41,
+          "text": "service: http://127.0.0.1:9926"
+        },
+        {
+          "line": 43,
+          "text": "service: http://127.0.0.1:9772"
+        }
+      ]
+    }
+  ],
+  "running_proxy_tunnel_processes": [
+    {
+      "pid": 1144,
+      "command": "nginx:",
+      "gracie_or_port_match": false,
+      "config_paths": [],
+      "ssh_forwarding": false,
+      "raw_args_omitted": true
+    },
+    {
+      "pid": 1458,
+      "command": "nginx:",
+      "gracie_or_port_match": false,
+      "config_paths": [],
+      "ssh_forwarding": false,
+      "raw_args_omitted": true
+    },
+    {
+      "pid": 3602,
+      "command": "ssh",
+      "gracie_or_port_match": false,
+      "config_paths": [],
+      "ssh_forwarding": false,
+      "raw_args_omitted": true
+    },
+    {
+      "pid": 59435,
+      "command": "ssh",
+      "gracie_or_port_match": false,
+      "config_paths": [],
+      "ssh_forwarding": false,
+      "raw_args_omitted": true
+    }
+  ],
+  "gracie_config_matches": [],
+  "gracie_process_matches": [],
+  "verdict": "PASS_BOUNDED_REVIEW",
+  "limits": [
+    "Cloud-managed ingress configurations and remote machine routes not queried",
+    "Loopback bind still requires post-apply listener and non-loopback rejection proof",
+    "No application imports, HTTP requests, jobs, sends, or config changes performed"
+  ],
+  "mandatory_checks": [
+    "Loopback-only10073 listener with noIPv6/wildcard listener",
+    "Non-loopback LAN and Tailscale addresses reject connection",
+    "Post-startup schema success before requestsGET",
+    "Auth missing/invalid401 and valid200",
+    "Catalog count/hash unchanged",
+    "Both configured PostgreSQL identities preserved and Unix-socket backend observed",
+    "Gracie effective/saved env fields agree; no explicit PGHOST defeats socket"
+  ],
+  "helper_review": {
+    "at": "2026-09-11T20:13:27.454671+00:00",
+    "sha256": "52bb37fe9e35758f74afe0af8b6c181e8dee6fe436ae5b3bf4150f92eee17dd1",
+    "verdict": "ACCEPT",
+    "scope": "server socket fallback and loopback bind, vendor pool host selection, exactly Gracie PG top/nested effective+saved fields",
+    "rollback": "Private source before/after/recovery copies; recovery retains127.0.0.1; before/after/recovery hashes accepted, other hashes rejected; repeated recovery and4partial states rehearsed",
+    "conditions": [
+      "Post-apply test all nonloopback local IPv4 interfaces including Tailscale if present",
+      "Confirm startup schema success before GET requests route; route retries DDL if schemaReady rejected"
+    ]
+  }
+}
diff --git a/verification/gracie-rollout/independent-runtime-firstfailure.json b/verification/gracie-rollout/independent-runtime-firstfailure.json
new file mode 100644
index 0000000..3de1888
--- /dev/null
+++ b/verification/gracie-rollout/independent-runtime-firstfailure.json
@@ -0,0 +1,35 @@
+{
+  "task": "TK-11438",
+  "owner": "codex-run-11438-verifier",
+  "at": "2026-09-11T20:16:55.205Z",
+  "assertions": [
+    {
+      "name": "Exact Gracie identity online after one restart",
+      "verdict": "PASS",
+      "detail": {
+        "pid": 91857,
+        "restarts": 2
+      }
+    },
+    {
+      "name": "Effective and saved PG socket fields agree; no PGHOST override",
+      "verdict": "PASS",
+      "detail": true
+    },
+    {
+      "name": "Auth/data-source/port controls unchanged",
+      "verdict": "PASS",
+      "detail": true
+    }
+  ],
+  "email_sends": 0,
+  "application_mutations": 0,
+  "pid": 91857,
+  "verdict": "FAIL",
+  "status": "partial",
+  "error": {
+    "name": "Error",
+    "code": "ENOENT",
+    "message": "ENOENT: no such file or directory, open '/tmp/tk11438-gracie-approved/private/server.privacy-rehearsal'"
+  }
+}
diff --git a/verification/gracie-rollout/independent-runtime.json b/verification/gracie-rollout/independent-runtime.json
new file mode 100644
index 0000000..8e508b7
--- /dev/null
+++ b/verification/gracie-rollout/independent-runtime.json
@@ -0,0 +1,260 @@
+{
+  "task": "TK-11438",
+  "owner": "codex-run-11438-verifier",
+  "at": "2026-09-11T20:23:15.787Z",
+  "checks": [
+    {
+      "name": "Exact Gracie online after one restart",
+      "verdict": "PASS",
+      "data": {
+        "pid": 91857,
+        "restarts": 2
+      }
+    },
+    {
+      "name": "Effective/saved socket fields and unchanged auth/data/port controls",
+      "verdict": "PASS",
+      "data": true
+    },
+    {
+      "name": "Reviewed source hashes, privacy rollback copies and catalog bundle",
+      "verdict": "PASS",
+      "data": true
+    },
+    {
+      "name": "Only 127.0.0.1:10073 listener and no TCP5432",
+      "verdict": "PASS",
+      "data": [
+        "node    91857 macstudio3   15u  IPv4 0x31f9c8265db2c7e5      0t0  TCP 127.0.0.1:10073 (LISTEN)"
+      ]
+    },
+    {
+      "name": "All nonloopback IPv4 plus IPv6 loopback reject 10073",
+      "verdict": "PASS",
+      "data": [
+        {
+          "host": "169.254.166.245",
+          "connected": false,
+          "code": "ECONNREFUSED"
+        },
+        {
+          "host": "169.254.223.128",
+          "connected": false,
+          "code": "ECONNREFUSED"
+        },
+        {
+          "host": "192.168.1.151",
+          "connected": false,
+          "code": "ECONNREFUSED"
+        },
+        {
+          "host": "192.168.1.134",
+          "connected": false,
+          "code": "ECONNREFUSED"
+        },
+        {
+          "host": "169.254.169.117",
+          "connected": false,
+          "code": "ECONNREFUSED"
+        },
+        {
+          "host": "169.254.2.38",
+          "connected": false,
+          "code": "ECONNREFUSED"
+        },
+        {
+          "host": "100.82.17.107",
+          "connected": false,
+          "code": "ECONNREFUSED"
+        },
+        {
+          "host": "169.254.128.95",
+          "connected": false,
+          "code": "ECONNREFUSED"
+        },
+        {
+          "host": "::1",
+          "connected": false,
+          "code": "ECONNREFUSED"
+        }
+      ]
+    },
+    {
+      "name": "/healthz missing",
+      "verdict": "PASS",
+      "data": {
+        "status": 200,
+        "body_sha256": "4062edaf750fb8074e7e83e0c9028c94e32468a8b6f1614774328ef045150f93",
+        "bytes": 11
+      }
+    },
+    {
+      "name": "/healthz invalid",
+      "verdict": "PASS",
+      "data": {
+        "status": 200,
+        "body_sha256": "4062edaf750fb8074e7e83e0c9028c94e32468a8b6f1614774328ef045150f93",
+        "bytes": 11
+      }
+    },
+    {
+      "name": "/healthz valid",
+      "verdict": "PASS",
+      "data": {
+        "status": 200,
+        "body_sha256": "4062edaf750fb8074e7e83e0c9028c94e32468a8b6f1614774328ef045150f93",
+        "bytes": 11
+      }
+    },
+    {
+      "name": "/api/products missing",
+      "verdict": "PASS",
+      "data": {
+        "status": 401,
+        "body_sha256": "45cceda8377a0f8cfb7a5dc927ee1760c648406764291c2032cbadad6e8e44fb",
+        "bytes": 24
+      }
+    },
+    {
+      "name": "/api/products invalid",
+      "verdict": "PASS",
+      "data": {
+        "status": 401,
+        "body_sha256": "45cceda8377a0f8cfb7a5dc927ee1760c648406764291c2032cbadad6e8e44fb",
+        "bytes": 24
+      }
+    },
+    {
+      "name": "/api/products valid",
+      "verdict": "PASS",
+      "data": {
+        "status": 200,
+        "body_sha256": "b01acb69f4bd1d7d3c64d4dead18b84cf7f7026e9a702a2e9a77b08f66940264",
+        "bytes": 188603
+      }
+    },
+    {
+      "name": "/api/requests missing",
+      "verdict": "PASS",
+      "data": {
+        "status": 401,
+        "body_sha256": "45cceda8377a0f8cfb7a5dc927ee1760c648406764291c2032cbadad6e8e44fb",
+        "bytes": 24
+      }
+    },
+    {
+      "name": "/api/requests invalid",
+      "verdict": "PASS",
+      "data": {
+        "status": 401,
+        "body_sha256": "45cceda8377a0f8cfb7a5dc927ee1760c648406764291c2032cbadad6e8e44fb",
+        "bytes": 24
+      }
+    },
+    {
+      "name": "/api/requests valid",
+      "verdict": "PASS",
+      "data": {
+        "status": 200,
+        "body_sha256": "4682017fdbc8ce5539bc7e44ef687440bfae054688ac409c289284cde01204c6",
+        "bytes": 197
+      }
+    },
+    {
+      "name": "Vendor socket identity and unchanged records/schema/indexes",
+      "verdict": "PASS",
+      "data": {
+        "identity": {
+          "database": "dw_unified",
+          "role": "dw_admin",
+          "addr": null,
+          "readonly": "on",
+          "database_oid": 16391,
+          "server_started": "2026-09-09T15:05:54.745Z"
+        },
+        "requests": {
+          "count": 1,
+          "last_id": "7"
+        }
+      }
+    },
+    {
+      "name": "Catalog effective socket identity",
+      "verdict": "PASS",
+      "data": {
+        "database": "dw_unified",
+        "role": "macstudio3",
+        "addr": null,
+        "readonly": "on"
+      }
+    },
+    {
+      "name": "Catalog saved socket identity",
+      "verdict": "PASS",
+      "data": {
+        "database": "dw_unified",
+        "role": "macstudio3",
+        "addr": null,
+        "readonly": "on"
+      }
+    },
+    {
+      "name": "vendor missing socket fails closed",
+      "verdict": "PASS",
+      "data": "ENOENT"
+    },
+    {
+      "name": "catalog missing socket fails closed",
+      "verdict": "PASS",
+      "data": "ENOENT"
+    },
+    {
+      "name": "Gracie owns Unix sockets",
+      "verdict": "PASS",
+      "data": {
+        "sha256": "186d9138e3b39fdf9897972970dd6b59a879e618554eea291fc3a66aaa28381b",
+        "rows": 5
+      }
+    },
+    {
+      "name": "Process stable throughout verification",
+      "verdict": "PASS",
+      "data": true
+    },
+    {
+      "name": "Commit changes exactly three lines across two scoped files",
+      "verdict": "PASS",
+      "data": {
+        "commit": "966130377ec694055a0688d0e1bd7f4bdf454a93",
+        "numstat": "1\t1\tlib/vendor-requests.js\n2\t2\tserver.js"
+      }
+    }
+  ],
+  "application_mutations": 0,
+  "email_sends": 0,
+  "pid": 91857,
+  "commit": "966130377ec694055a0688d0e1bd7f4bdf454a93",
+  "verdict": "PASS",
+  "status": "complete_scoped_verification",
+  "scope_limits": [
+    "17 local proxy configs and 4 running proxy/tunnel processes inspected before rollout; remote/cloud-managed routes unqueried",
+    "Catalog currently uses unchanged JSONL; configured PG URI independently connected",
+    "Only GET routes after confirmed startup DDL; no POST or emails"
+  ],
+  "commands": [
+    "Direct existing PM2 monitor RPC before/after",
+    "lsof process TCP/Unix",
+    "TCP connect all nonloopback IPv4 and ::1",
+    "9 loopback GET auth checks",
+    "Read-only PostgreSQL identity/count/schema/index queries",
+    "Source/rollback-copy/catalog bundle SHA256",
+    "git rev-parse and show --numstat"
+  ],
+  "execution_provenance": {
+    "checker": "/tmp/tk11438-gracie-approved/independent-check.cjs",
+    "authored_and_reviewed_by": "codex-run-11438-verifier",
+    "executed_by": "parent through scoped host approval",
+    "final_artifact_independently_inspected_at": "2026-09-11T20:23:52.883501+00:00",
+    "initial_verifier_failure": "independent-runtime-firstfailure.json; filename typo fixed, no application regression"
+  }
+}
diff --git a/verification/gracie-rollout/monitor.json b/verification/gracie-rollout/monitor.json
new file mode 100644
index 0000000..4bac1dd
--- /dev/null
+++ b/verification/gracie-rollout/monitor.json
@@ -0,0 +1,252 @@
+{
+  "at": "2026-09-11T20:16:18.263Z",
+  "pid": 91857,
+  "pm_id": 12,
+  "restarts": 2,
+  "controls": {
+    "auth_sha": "[stored in private rollback evidence]",
+    "PGHOST": null,
+    "nested_PGHOST": null,
+    "DATA_SOURCE": null,
+    "PORT": "10073",
+    "cwd": "/Users/macstudio3/Projects/gracie-internal",
+    "script": "/Users/macstudio3/Projects/gracie-internal/server.js"
+  },
+  "http": [
+    {
+      "route": "/healthz",
+      "auth": "missing",
+      "status": 200,
+      "body_sha": "4062edaf750fb8074e7e83e0c9028c94e32468a8b6f1614774328ef045150f93",
+      "bytes": 11
+    },
+    {
+      "route": "/healthz",
+      "auth": "invalid",
+      "status": 200,
+      "body_sha": "4062edaf750fb8074e7e83e0c9028c94e32468a8b6f1614774328ef045150f93",
+      "bytes": 11
+    },
+    {
+      "route": "/healthz",
+      "auth": "valid",
+      "status": 200,
+      "body_sha": "4062edaf750fb8074e7e83e0c9028c94e32468a8b6f1614774328ef045150f93",
+      "bytes": 11
+    },
+    {
+      "route": "/api/products",
+      "auth": "missing",
+      "status": 401,
+      "body_sha": "45cceda8377a0f8cfb7a5dc927ee1760c648406764291c2032cbadad6e8e44fb",
+      "bytes": 24
+    },
+    {
+      "route": "/api/products",
+      "auth": "invalid",
+      "status": 401,
+      "body_sha": "45cceda8377a0f8cfb7a5dc927ee1760c648406764291c2032cbadad6e8e44fb",
+      "bytes": 24
+    },
+    {
+      "route": "/api/products",
+      "auth": "valid",
+      "status": 200,
+      "body_sha": "b01acb69f4bd1d7d3c64d4dead18b84cf7f7026e9a702a2e9a77b08f66940264",
+      "bytes": 188603
+    },
+    {
+      "route": "/api/requests",
+      "auth": "missing",
+      "status": 401,
+      "body_sha": "45cceda8377a0f8cfb7a5dc927ee1760c648406764291c2032cbadad6e8e44fb",
+      "bytes": 24
+    },
+    {
+      "route": "/api/requests",
+      "auth": "invalid",
+      "status": 401,
+      "body_sha": "45cceda8377a0f8cfb7a5dc927ee1760c648406764291c2032cbadad6e8e44fb",
+      "bytes": 24
+    },
+    {
+      "route": "/api/requests",
+      "auth": "valid",
+      "status": 200,
+      "body_sha": "4682017fdbc8ce5539bc7e44ef687440bfae054688ac409c289284cde01204c6",
+      "bytes": 197
+    }
+  ],
+  "product_count": 150,
+  "vendor": {
+    "identity": {
+      "database": "dw_unified",
+      "role": "dw_admin",
+      "addr": null,
+      "readonly": "on",
+      "database_oid": 16391,
+      "server_started": "2026-09-09T15:05:54.745Z"
+    },
+    "requests": {
+      "count": 1,
+      "last_id": "7"
+    },
+    "schema": [
+      {
+        "column_name": "id",
+        "data_type": "bigint",
+        "is_nullable": "NO",
+        "column_default": "nextval('vendor_requests_id_seq'::regclass)"
+      },
+      {
+        "column_name": "req_no",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "req_type",
+        "data_type": "text",
+        "is_nullable": "NO",
+        "column_default": null
+      },
+      {
+        "column_name": "vendor_code",
+        "data_type": "text",
+        "is_nullable": "NO",
+        "column_default": null
+      },
+      {
+        "column_name": "vendor_name",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "vendor_email",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "account_number",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "dw_sku",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "mfr_sku",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "product_title",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "qty",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "note",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "requested_by",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "status",
+        "data_type": "text",
+        "is_nullable": "NO",
+        "column_default": "'open'::text"
+      },
+      {
+        "column_name": "email_subject",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "email_body",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "email_message_id",
+        "data_type": "text",
+        "is_nullable": "YES",
+        "column_default": null
+      },
+      {
+        "column_name": "created_at",
+        "data_type": "timestamp with time zone",
+        "is_nullable": "NO",
+        "column_default": "now()"
+      },
+      {
+        "column_name": "sent_at",
+        "data_type": "timestamp with time zone",
+        "is_nullable": "YES",
+        "column_default": null
+      }
+    ],
+    "indexes": [
+      {
+        "indexname": "idx_vendor_requests_vendor",
+        "indexdef": "CREATE INDEX idx_vendor_requests_vendor ON public.vendor_requests USING btree (vendor_code, created_at DESC)"
+      },
+      {
+        "indexname": "vendor_requests_pkey",
+        "indexdef": "CREATE UNIQUE INDEX vendor_requests_pkey ON public.vendor_requests USING btree (id)"
+      },
+      {
+        "indexname": "vendor_requests_req_no_key",
+        "indexdef": "CREATE UNIQUE INDEX vendor_requests_req_no_key ON public.vendor_requests USING btree (req_no)"
+      },
+      {
+        "indexname": "vendor_requests_vendor_code_id_idx",
+        "indexdef": "CREATE INDEX vendor_requests_vendor_code_id_idx ON public.vendor_requests USING btree (vendor_code, id DESC)"
+      }
+    ]
+  },
+  "catalog": {
+    "database": "dw_unified",
+    "role": "macstudio3",
+    "addr": null,
+    "readonly": "on"
+  },
+  "vendor_config": {
+    "host": "/tmp",
+    "database": "dw_unified",
+    "user": "dw_admin",
+    "port": 5432
+  },
+  "saved_match": true,
+  "listeners": [
+    "node    91857 macstudio3   15u  IPv4 0x31f9c8265db2c7e5      0t0  TCP 127.0.0.1:10073 (LISTEN)"
+  ],
+  "database_tcp": [],
+  "source_hashes": {
+    "server": "d577f28fe6b305bfad4ba29c5a00fbbf896ec963f016546e4873e7ca57a2ba21",
+    "vendor": "d87ab5d2e4d44953aea64befe63c033dc0bc8479c3bc11fc5328c7bfb6d8690e"
+  },
+  "bundle_sha": "764cfa9e2ac274c272c04326ffda8856eda425c721555edbc875bf31e5d9c5d6",
+  "email_sends": 0
+}
diff --git a/verification/gracie-rollout/mutation-started.json b/verification/gracie-rollout/mutation-started.json
new file mode 100644
index 0000000..46eff5b
--- /dev/null
+++ b/verification/gracie-rollout/mutation-started.json
@@ -0,0 +1,5 @@
+{
+  "at": "2026-09-11T20:14:16.142Z",
+  "scope": "Gracie only; local/private",
+  "restart_requested": false
+}
diff --git a/verification/gracie-rollout/observation.json b/verification/gracie-rollout/observation.json
new file mode 100644
index 0000000..33fe2f4
--- /dev/null
+++ b/verification/gracie-rollout/observation.json
@@ -0,0 +1,58 @@
+{
+  "at": "2026-09-11T20:16:20.312Z",
+  "verdict": "PASS",
+  "pid": 91857,
+  "auth_checks": 9,
+  "product_count": 150,
+  "role_database_preserved": true,
+  "request_records_unchanged": true,
+  "schema_unchanged": true,
+  "both_transports_socket": true,
+  "process_tcp5432": false,
+  "durable_match": true,
+  "listener": "127.0.0.1:10073",
+  "networkChecks": [
+    {
+      "name": "en3",
+      "address": "169.254.166.245",
+      "result": "connection failed"
+    },
+    {
+      "name": "en6",
+      "address": "169.254.223.128",
+      "result": "connection failed"
+    },
+    {
+      "name": "en0",
+      "address": "192.168.1.151",
+      "result": "connection failed"
+    },
+    {
+      "name": "en1",
+      "address": "192.168.1.134",
+      "result": "connection failed"
+    },
+    {
+      "name": "en15",
+      "address": "169.254.169.117",
+      "result": "connection failed"
+    },
+    {
+      "name": "en18",
+      "address": "169.254.2.38",
+      "result": "connection failed"
+    },
+    {
+      "name": "utun6",
+      "address": "100.82.17.107",
+      "result": "connection failed"
+    },
+    {
+      "name": "en20",
+      "address": "169.254.128.95",
+      "result": "connection failed"
+    }
+  ],
+  "missing_socket": "ENOENT",
+  "email_sends": 0
+}
diff --git a/verification/gracie-rollout/preparation.json b/verification/gracie-rollout/preparation.json
new file mode 100644
index 0000000..e805ed2
--- /dev/null
+++ b/verification/gracie-rollout/preparation.json
@@ -0,0 +1,9 @@
+{
+  "at": "2026-09-11T20:12:30.798Z",
+  "verdict": "PASS",
+  "rollback_rehearsal": "2 exact files plus 2 Gracie dump fields; 4 partial-mutation cases and peer-edit refusal",
+  "private_mode": 448,
+  "privacy": "localhost-only bind required by Steve",
+  "application_mutations": 0,
+  "email_sends": 0
+}
diff --git a/verification/gracie-rollout/restart-requested.json b/verification/gracie-rollout/restart-requested.json
new file mode 100644
index 0000000..3695876
--- /dev/null
+++ b/verification/gracie-rollout/restart-requested.json
@@ -0,0 +1,5 @@
+{
+  "at": "2026-09-11T20:14:16.208Z",
+  "before_pid": 8186,
+  "pm_id": 12
+}
diff --git a/verification/gracie-rollout/rollout.cjs b/verification/gracie-rollout/rollout.cjs
new file mode 100644
index 0000000..e101495
--- /dev/null
+++ b/verification/gracie-rollout/rollout.cjs
@@ -0,0 +1,79 @@
+// Approved TK11438 local Gracie-only migration. No email, publishing or remote ops.
+const fs=require('fs'),path=require('path'),crypto=require('crypto'),cp=require('child_process'),assert=require('assert/strict'),vm=require('vm'),os=require('os');
+const ROOT='/Users/macstudio3/Projects/gracie-internal',OUT=__dirname,PRIV=OUT+'/private',DUMP='/Users/macstudio3/.pm2/dump.pm2';
+const EVIDENCE='/Users/macstudio3/Projects/tk11438-postgres-migration/verification/fleet-classification';
+const {Client}=require(ROOT+'/node_modules/pg');
+const deps='/Users/macstudio3/.npm-global/lib/node_modules/pm2/node_modules/';
+const axon=require(deps+'pm2-axon'),rpc=require(deps+'pm2-axon-rpc');
+const mode=process.argv[2];assert(['prepare','apply','verify','observe','rollback'].includes(mode));
+const sha=x=>crypto.createHash('sha256').update(x).digest('hex');
+const json=p=>JSON.parse(fs.readFileSync(p));
+const record=(name,x)=>fs.writeFileSync(OUT+'/'+name+'.json',JSON.stringify({at:new Date().toISOString(),...x},(k,v)=>k==='auth_sha'?'[stored in private rollback evidence]':v,2)+'\n');
+const run=(cmd,args,opts={})=>cp.execFileSync(cmd,args,{encoding:'utf8',timeout:15000,maxBuffer:10*1024*1024,...opts});
+const git=(...args)=>run('git',args,{cwd:ROOT}).trim();
+const rpcCall=(method,opts={})=>new Promise((resolve,reject)=>{const sock=axon.socket('req'),client=new rpc.Client(sock);const t=setTimeout(()=>{sock.close();reject(Error('RPC timeout '+method));},30000);sock.on('error',e=>{clearTimeout(t);sock.close();reject(e);});sock.connect('/Users/macstudio3/.pm2/rpc.sock');client.call(method,opts,(err,data)=>{clearTimeout(t);sock.close();err?reject(Error('RPC failure '+method)):resolve(data);});});
+function unique(list){const a=list.filter(x=>x.name==='gracie-internal');assert.equal(a.length,1);const x=a[0],e=x.pm2_env||x;assert.equal(e.pm_cwd,ROOT);assert.equal(e.pm_exec_path,ROOT+'/server.js');return x;}
+function fields(e){assert(e.env);return{PG:e.PG,env:{PG:e.env.PG}};}
+function setFields(e,v){e.PG=v.PG;e.env.PG=v.env.PG;}
+function socketURL(s){const u=new URL(s);assert(['localhost','127.0.0.1','[::1]',''].includes(u.hostname));assert.equal(u.pathname,'/dw_unified');assert(['','5432'].includes(u.port));u.searchParams.set('host','/tmp');return u.toString();}
+function atomic(file,bytes,expected){assert.equal(sha(fs.readFileSync(file)),expected,'concurrent file change '+file);const temp=file+'.TK11438-'+process.pid;fs.writeFileSync(temp,bytes,{flag:'wx',mode:fs.statSync(file).mode&0o777});assert.equal(sha(fs.readFileSync(file)),expected);fs.renameSync(temp,file);assert.equal(sha(fs.readFileSync(file)),sha(bytes));}
+function patchDump(expected,next){const bytes=fs.readFileSync(DUMP),d=JSON.parse(bytes);assert.deepEqual(fields(unique(d)),expected);setFields(unique(d),next);const restored=JSON.parse(JSON.stringify(d));setFields(unique(restored),expected);assert.deepEqual(restored,JSON.parse(bytes));atomic(DUMP,JSON.stringify(d,null,2),sha(bytes));return{only_gracie_two_fields:true};}
+function controls(e){return{auth_sha:sha(e.BASIC_AUTH||''),PGHOST:e.PGHOST||null,nested_PGHOST:e.env?.PGHOST||null,DATA_SOURCE:e.DATA_SOURCE||null,PORT:String(e.PORT||10073),cwd:e.pm_cwd,script:e.pm_exec_path};}
+function dbOpts(source,e){let captured;const match=source.match(/let pool = null;\s*function db\(\) \{[\s\S]*?\n\}/);assert(match);const secret=fs.readFileSync('/Users/macstudio3/Projects/secrets-manager/.env','utf8').match(/^DW_ADMIN_DB_PASSWORD=(.+)$/m);const pass=e.DW_ADMIN_DB_PASSWORD||(secret?secret[1].replace(/^["']|["']$/g,'').trim():'');vm.runInNewContext(match[0]+';db();',{process:{platform:process.platform,env:e},PGPASS:pass,Pool:class{constructor(o){captured=o;}}},{timeout:1000});return captured;}
+async function withDb(options,fn){const c=new Client({...options,application_name:'TK11438-Gracie-'+mode,connectionTimeoutMillis:4000,options:'-c default_transaction_read_only=on -c statement_timeout=5000'});try{await c.connect();return await fn(c);}finally{await c.end().catch(()=>{});}}
+async function dataProof(options){return withDb(options,async c=>({identity:(await c.query("SELECT current_database() database,current_user role,inet_client_addr()::text addr,current_setting('transaction_read_only') readonly,(SELECT oid FROM pg_database WHERE datname=current_database()) database_oid,pg_postmaster_start_time() server_started")).rows[0],requests:(await c.query("SELECT count(*)::int count,max(id)::text last_id FROM vendor_requests WHERE vendor_code='gracie'")).rows[0],schema:(await c.query("SELECT column_name,data_type,is_nullable,column_default FROM information_schema.columns WHERE table_schema='public' AND table_name='vendor_requests' ORDER BY ordinal_position")).rows,indexes:(await c.query("SELECT indexname,indexdef FROM pg_indexes WHERE schemaname='public' AND tablename='vendor_requests' ORDER BY indexname")).rows}));}
+function lsof(pid){try{return run('lsof',['-nP','-a','-p',String(pid),'-iTCP']);}catch(e){if(e.status===1)return e.stdout||'';throw e;}}
+async function snapshot(name,requests=false){const p=unique(await rpcCall('getMonitorData')),e=p.pm2_env;assert.equal(e.status,'online');const source=fs.readFileSync(ROOT+'/server.js','utf8'),poolSource=fs.readFileSync(ROOT+'/lib/vendor-requests.js','utf8');const auth=e.BASIC_AUTH||source.match(/process\.env\.BASIC_AUTH \|\| '([^']+)'/)[1];
+ const checks=[];let count;for(const route of ['/healthz','/api/products',...(requests?['/api/requests']:[])])for(const [label,a]of [['missing',null],['invalid','invalid:invalid'],['valid',auth]]){const r=await fetch('http://127.0.0.1:'+String(e.PORT||10073)+route,{headers:a?{authorization:'Basic '+Buffer.from(a).toString('base64')}:{},signal:AbortSignal.timeout(8000)});const body=await r.text();assert.equal(r.status,route==='/healthz'||label==='valid'?200:401,route+' '+label);if(label==='valid'&&route==='/api/products')count=JSON.parse(body).count;if(label==='valid'&&route==='/api/requests')assert(Array.isArray(JSON.parse(body).requests));checks.push({route,auth:label,status:r.status,body_sha:sha(body),bytes:Buffer.byteLength(body)});}
+ const pool=dbOpts(poolSource,e),vendor=await dataProof(pool),catalog=await withDb({connectionString:e.PG},async c=>(await c.query("SELECT current_database() database,current_user role,inet_client_addr()::text addr,current_setting('transaction_read_only') readonly")).rows[0]);
+ const tcp=lsof(p.pid).split('\n').filter(Boolean),proof={pid:p.pid,pm_id:e.pm_id,restarts:e.restart_time,controls:controls(e),http:checks,product_count:count,vendor,catalog,vendor_config:{host:pool.host,database:pool.database,user:pool.user,port:pool.port},saved_match:JSON.stringify(fields(e))===JSON.stringify(fields(unique(json(DUMP)))),listeners:tcp.filter(l=>/LISTEN/.test(l)),database_tcp:tcp.filter(l=>/:5432\b/.test(l)),source_hashes:{server:sha(source),vendor:sha(poolSource)},bundle_sha:sha(fs.readFileSync(ROOT+'/data/gracie.jsonl')),email_sends:0};record(name,proof);return proof;
+}
+function fileSpecs(){const pre=json(EVIDENCE+'/gracie-preflight.json'),shared=json(EVIDENCE+'/shared-modules.json'),entry=shared.modules.find(x=>x.path===ROOT+'/lib/vendor-requests.js');const oldServer=fs.readFileSync(ROOT+'/server.js','utf8'),oldVendor=fs.readFileSync(entry.path,'utf8');assert.equal(sha(oldServer),pre.source.before_sha256);assert.equal(sha(oldVendor),entry.sha256);
+ const old="const PG = process.env.PG || 'postgresql://localhost/dw_unified';",next="const PG = process.env.PG || (process.platform === 'darwin' ? 'postgresql://localhost/dw_unified?host=/tmp' : 'postgresql://localhost/dw_unified');";
+ const bindOld='app.listen(PORT, () =>',bindNew="app.listen(PORT, '127.0.0.1', () =>";assert.equal(oldServer.split(old).length-1,1);assert.equal(oldServer.split(bindOld).length-1,1);assert.equal(oldVendor.split(shared.proposed_old).length-1,1);
+ return[{key:'server',path:ROOT+'/server.js',before:oldServer,after:oldServer.replace(old,next).replace(bindOld,bindNew)},{key:'vendor',path:entry.path,before:oldVendor,after:oldVendor.replace(shared.proposed_old,shared.proposed_new)}];}
+function restorationActions(specs,getCurrent){return specs.map(s=>{const current=getCurrent(s.path);assert([s.before_sha,s.after_sha,s.recovery_sha].includes(current),'peer edit blocks rollback');return{...s,current,restore:current!==s.recovery_sha};});}
+(async()=>{
+ if(mode==='prepare'){
+  assert(!fs.existsSync(PRIV),'already prepared');assert.equal(git('status','--porcelain'),'');const p=unique(await rpcCall('getMonitorData')),e=p.pm2_env,before=fields(e);assert.deepEqual(before,fields(unique(json(DUMP))));assert.equal(before.PG,before.env.PG);assert(!e.PGHOST&&!e.env.PGHOST,'unexpected override');const next={PG:socketURL(before.PG),env:{PG:socketURL(before.env.PG)}};const specs=fileSpecs();
+  for(const s of specs)run('node',['--check'],{input:s.after});const baseline=await snapshot('baseline',false);assert.equal(baseline.vendor.identity.database,'dw_unified');assert.equal(baseline.vendor.identity.role,'dw_admin');assert(baseline.vendor.schema.length>0,'Existing table required');
+  for(const s of specs)s.recovery=s.key==='server'?s.before.replace('app.listen(PORT, () =>',"app.listen(PORT, '127.0.0.1', () =>"):s.before;
+  fs.mkdirSync(PRIV,{mode:0o700});fs.writeFileSync(PRIV+'/baseline.runtime.json',JSON.stringify(baseline),{mode:0o600,flag:'wx'});for(const s of specs)for(const side of ['before','after','recovery'])fs.writeFileSync(PRIV+'/'+s.key+'.'+side,s[side],{mode:0o600,flag:'wx'});
+  const receipt={head:git('rev-parse','HEAD'),pid:p.pid,pm_id:e.pm_id,before,next,controls:controls(e),specs:specs.map(s=>({key:s.key,path:s.path,before_sha:sha(s.before),after_sha:sha(s.after),recovery_sha:sha(s.recovery)}))};fs.writeFileSync(PRIV+'/receipt.json',JSON.stringify(receipt,null,2),{mode:0o600,flag:'wx'});
+  // Rehearse changes and restoration on private copies, and both PG fields only.
+  for(const s of receipt.specs){const f=PRIV+'/rehearsal-'+s.key;fs.copyFileSync(PRIV+'/'+s.key+'.before',f);atomic(f,fs.readFileSync(PRIV+'/'+s.key+'.after'),s.before_sha);atomic(f,fs.readFileSync(PRIV+'/'+s.key+'.before'),s.after_sha);assert.equal(sha(fs.readFileSync(f)),s.before_sha);}
+  const d=json(DUMP),original=JSON.parse(JSON.stringify(d));setFields(unique(d),next);setFields(unique(d),before);assert.deepEqual(d,original);
+  for(const mask of [0,1,2,3])for(const action of restorationActions(receipt.specs,(f)=>{const i=receipt.specs.findIndex(s=>s.path===f),s=receipt.specs[i];return(mask&(1<<i))?s.after_sha:s.before_sha;}))assert.equal(action.restore,action.current!==action.recovery_sha);
+  assert(restorationActions(receipt.specs,f=>receipt.specs.find(s=>s.path===f).recovery_sha).every(s=>!s.restore));
+  for(const s of receipt.specs){const f=PRIV+'/privacy-rehearsal-'+s.key;fs.copyFileSync(PRIV+'/'+s.key+'.after',f);atomic(f,fs.readFileSync(PRIV+'/'+s.key+'.recovery'),s.after_sha);assert.equal(sha(fs.readFileSync(f)),s.recovery_sha);if(s.key==='server')assert(fs.readFileSync(f,'utf8').includes("app.listen(PORT, '127.0.0.1', () =>"));run('node',['--check'],{input:fs.readFileSync(f,'utf8')});}
+  assert.throws(()=>restorationActions(receipt.specs,()=>sha('peer edit')));
+  record('preparation',{verdict:'PASS',rollback_rehearsal:'2 exact files plus 2 Gracie dump fields; 4 partial-mutation cases and peer-edit refusal',private_mode:fs.statSync(PRIV).mode&0o777,privacy:'localhost-only bind required by Steve',application_mutations:0,email_sends:0});
+ }else if(mode==='apply'){
+  const rec=json(PRIV+'/receipt.json');assert.equal(json(OUT+'/preparation.json').verdict,'PASS');assert(!fs.existsSync(OUT+'/mutation-started.json'),'already started; use rollback or verify');assert.equal(git('status','--porcelain'),'');assert.equal(git('rev-parse','HEAD'),rec.head);const p=unique(await rpcCall('getMonitorData'));assert.equal(p.pid,rec.pid);assert.deepEqual(fields(p.pm2_env),rec.before);assert.deepEqual(controls(p.pm2_env),rec.controls);assert.deepEqual(fields(unique(json(DUMP))),rec.before);
+  for(const s of rec.specs)assert.equal(sha(fs.readFileSync(s.path)),s.before_sha);record('mutation-started',{scope:'Gracie only; local/private',restart_requested:false});
+  for(const s of rec.specs)atomic(s.path,fs.readFileSync(PRIV+'/'+s.key+'.after'),s.before_sha);const dump=patchDump(rec.before,rec.next);record('config-applied',{dump,privacy:'127.0.0.1 listener in source'});
+  const errPath=p.pm2_env.pm_err_log_path;record('error-log-baseline',{path:errPath,size:fs.existsSync(errPath)?fs.statSync(errPath).size:0});
+  record('restart-requested',{before_pid:p.pid,pm_id:rec.pm_id});await rpcCall('restartProcessId',{id:rec.pm_id,env:{PG:rec.next.PG}});const after=unique(await rpcCall('getMonitorData'));assert.notEqual(after.pid,rec.pid);record('applied',{verdict:'APPLIED_VERIFY_PENDING',pid:after.pid,previous_pid:rec.pid});
+ }else if(mode==='verify'||mode==='observe'){
+  if(mode==='verify'&&!fs.existsSync(OUT+'/startup-schema.json')){
+   const log=json(OUT+'/error-log-baseline.json'),bytes=fs.existsSync(log.path)?fs.readFileSync(log.path):Buffer.alloc(0);assert(bytes.length>=log.size,'error log rotated');const tail=bytes.subarray(log.size).toString();assert(!/ensureSchema failed|\[gracie-internal\] load failed/i.test(tail),'startup failure; do not invoke request GET');
+   const started=json(OUT+'/restart-requested.json').at;
+   const completed=await withDb({connectionString:'postgresql:///postgres?host=/tmp'},async c=>(await c.query("SELECT pid,backend_start,state,client_addr::text addr FROM pg_stat_activity WHERE datname='dw_unified' AND usename='dw_admin' AND backend_start >= $1 AND client_addr IS NULL AND state='idle' AND query LIKE '%CREATE TABLE IF NOT EXISTS vendor_requests%'",[started])).rows);
+   assert(completed.length>0,'await completed socket startup DDL before request GET');record('startup-schema',{verdict:'PASS',socket_idle_ddl_backends:completed,error_log_new_bytes:tail.length,error_log_tail_sha:sha(tail),note:'New idle socket backend after startup DDL and no schema error logged; bounded source/runtime correlation'});
+  }
+  const rec=json(PRIV+'/receipt.json'),baseline=json(PRIV+'/baseline.runtime.json'),p=await snapshot(mode==='verify'?'after':'monitor',true);assert(p.saved_match);assert.deepEqual(p.controls,baseline.controls);assert.equal(p.product_count,baseline.product_count);assert.equal(p.bundle_sha,baseline.bundle_sha);assert.deepEqual(p.vendor.requests,baseline.vendor.requests);assert.deepEqual(p.vendor.schema,baseline.vendor.schema);assert.deepEqual(p.vendor.indexes,baseline.vendor.indexes);
+  assert.equal(p.vendor.identity.addr,null);assert.equal(p.catalog.addr,null);assert.equal(p.vendor.identity.readonly,'on');assert.equal(p.catalog.readonly,'on');assert.deepEqual([p.vendor.identity.database,p.vendor.identity.role,p.vendor.identity.database_oid,new Date(p.vendor.identity.server_started).toISOString()],[baseline.vendor.identity.database,baseline.vendor.identity.role,baseline.vendor.identity.database_oid,new Date(baseline.vendor.identity.server_started).toISOString()]);assert.deepEqual([p.catalog.database,p.catalog.role],[baseline.catalog.database,baseline.catalog.role]);assert.equal(p.vendor_config.host,'/tmp');assert.equal(p.database_tcp.length,0);assert.equal(p.listeners.length,1);assert(/127\.0\.0\.1:10073\s+\(LISTEN\)/.test(p.listeners[0]));
+  for(const s of rec.specs)assert.equal(sha(fs.readFileSync(s.path)),s.after_sha);const e=unique(await rpcCall('getMonitorData')).pm2_env;assert.deepEqual(fields(e),rec.next);assert.deepEqual(fields(unique(json(DUMP))),rec.next);
+  const bad=new Client({host:OUT+'/missing-socket',database:'dw_unified',connectionTimeoutMillis:1000});let code;try{await bad.connect();}catch(err){code=err.code;}finally{await bad.end().catch(()=>{});}assert.equal(code,'ENOENT');
+  const interfaces=Object.entries(os.networkInterfaces()).flatMap(([name,rows])=>rows.filter(x=>x.family==='IPv4'&&!x.internal).map(x=>({name,address:x.address}))),networkChecks=[];
+  for(const iface of interfaces){let refused=false;try{await fetch('http://'+iface.address+':10073/healthz',{signal:AbortSignal.timeout(3000)});}catch(err){refused=true;}assert(refused,'Gracie reachable over nonloopback interface');networkChecks.push({...iface,result:'connection failed'});}
+  if(mode==='observe'){const after=json(OUT+'/after.json');assert.equal(p.pid,after.pid);assert.equal(p.restarts,after.restarts);}
+  record(mode==='verify'?'verification':'observation',{verdict:'PASS',pid:p.pid,auth_checks:p.http.length,product_count:p.product_count,role_database_preserved:true,request_records_unchanged:true,schema_unchanged:true,both_transports_socket:true,process_tcp5432:false,durable_match:true,listener:'127.0.0.1:10073',networkChecks,missing_socket:code,email_sends:0});
+ }else if(mode==='rollback'){
+  const rec=json(PRIV+'/receipt.json');assert(fs.existsSync(OUT+'/mutation-started.json'));const actions=restorationActions(rec.specs,f=>sha(fs.readFileSync(f)));const current=fields(unique(json(DUMP)));assert([JSON.stringify(rec.before),JSON.stringify(rec.next)].includes(JSON.stringify(current)));const e=unique(await rpcCall('getMonitorData')).pm2_env;assert.deepEqual(controls(e),rec.controls);
+  // Privacy persists through recovery: restore transport, retain localhost bind.
+  for(const s of actions)if(s.restore)atomic(s.path,fs.readFileSync(PRIV+'/'+s.key+'.recovery'),s.current);
+  if(JSON.stringify(current)!==JSON.stringify(rec.before))patchDump(rec.next,rec.before);await rpcCall('restartProcessId',{id:rec.pm_id,env:{PG:rec.before.PG}});record('rollback',{verdict:'TRANSPORT_RESTORED_VERIFY_REQUIRED',privacy:'localhost binding retained per Steve; no reopening wildcard',baseline_semantics:'transport restored; intentional privacy change remains'});
+ }
+ console.log(JSON.stringify({mode,verdict:'PASS',evidence:OUT}));
+})().catch(err=>{record(mode+'-failure',{verdict:'FAIL',code:err.code||err.name,message:String(err.message).replace(/postgres(?:ql)?:\/\/\S+/g,'[REDACTED_URI]')});console.error(JSON.stringify({mode,verdict:'FAIL',code:err.code||err.name,message:String(err.message).replace(/postgres(?:ql)?:\/\/\S+/g,'[REDACTED_URI]')}));process.exitCode=1;});
diff --git a/verification/gracie-rollout/startup-schema.json b/verification/gracie-rollout/startup-schema.json
new file mode 100644
index 0000000..6c7c139
--- /dev/null
+++ b/verification/gracie-rollout/startup-schema.json
@@ -0,0 +1,15 @@
+{
+  "at": "2026-09-11T20:14:18.916Z",
+  "verdict": "PASS",
+  "socket_idle_ddl_backends": [
+    {
+      "pid": 91868,
+      "backend_start": "2026-09-11T20:14:16.755Z",
+      "state": "idle",
+      "addr": null
+    }
+  ],
+  "error_log_new_bytes": 0,
+  "error_log_tail_sha": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+  "note": "New idle socket backend after startup DDL and no schema error logged; bounded source/runtime correlation"
+}
diff --git a/verification/gracie-rollout/verification.json b/verification/gracie-rollout/verification.json
new file mode 100644
index 0000000..c347a5b
--- /dev/null
+++ b/verification/gracie-rollout/verification.json
@@ -0,0 +1,58 @@
+{
+  "at": "2026-09-11T20:14:52.080Z",
+  "verdict": "PASS",
+  "pid": 91857,
+  "auth_checks": 9,
+  "product_count": 150,
+  "role_database_preserved": true,
+  "request_records_unchanged": true,
+  "schema_unchanged": true,
+  "both_transports_socket": true,
+  "process_tcp5432": false,
+  "durable_match": true,
+  "listener": "127.0.0.1:10073",
+  "networkChecks": [
+    {
+      "name": "en3",
+      "address": "169.254.166.245",
+      "result": "connection failed"
+    },
+    {
+      "name": "en6",
+      "address": "169.254.223.128",
+      "result": "connection failed"
+    },
+    {
+      "name": "en0",
+      "address": "192.168.1.151",
+      "result": "connection failed"
+    },
+    {
+      "name": "en1",
+      "address": "192.168.1.134",
+      "result": "connection failed"
+    },
+    {
+      "name": "en15",
+      "address": "169.254.169.117",
+      "result": "connection failed"
+    },
+    {
+      "name": "en18",
+      "address": "169.254.2.38",
+      "result": "connection failed"
+    },
+    {
+      "name": "utun6",
+      "address": "100.82.17.107",
+      "result": "connection failed"
+    },
+    {
+      "name": "en20",
+      "address": "169.254.128.95",
+      "result": "connection failed"
+    }
+  ],
+  "missing_socket": "ENOENT",
+  "email_sends": 0
+}
diff --git a/verification/gracie-rollout/verify-failure.json b/verification/gracie-rollout/verify-failure.json
new file mode 100644
index 0000000..5e9bdb3
--- /dev/null
+++ b/verification/gracie-rollout/verify-failure.json
@@ -0,0 +1,6 @@
+{
+  "at": "2026-09-11T20:14:20.794Z",
+  "verdict": "FAIL",
+  "code": "ERR_ASSERTION",
+  "message": "Expected values to be strictly deep-equal:\n+ actual - expected\n\n  [\n    'dw_unified',\n    'dw_admin',\n    16391,\n+   2026-09-09T15:05:54.745Z\n-   '2026-09-09T15:05:54.745Z'\n  ]\n"
+}

← b4b5e5c Classify remaining PostgreSQL consumers and prepare Gracie s  ·  back to Tk11438 Postgres Migration  ·  Verify existing Gracie domain and All-DW catalog link 469a2b2 →