← back to Tk11438 Postgres Migration
Record verified private Gracie socket migration
676734b717b2e05b807b7ed95372ccaffc4f6593 · 2026-09-11 13:28:45 -0700 · Steve Abrams
Files touched
M .gitignoreM GRACIE-BATCH.mdM README.mdA verification/gracie-rollout/after.jsonA verification/gracie-rollout/applied.jsonA verification/gracie-rollout/baseline.jsonA verification/gracie-rollout/config-applied.jsonA verification/gracie-rollout/e2e-proof.jsonA verification/gracie-rollout/error-log-baseline.jsonA verification/gracie-rollout/independent-check.cjsA verification/gracie-rollout/independent-preflight.jsonA verification/gracie-rollout/independent-runtime-firstfailure.jsonA verification/gracie-rollout/independent-runtime.jsonA verification/gracie-rollout/monitor.jsonA verification/gracie-rollout/mutation-started.jsonA verification/gracie-rollout/observation.jsonA verification/gracie-rollout/preparation.jsonA verification/gracie-rollout/restart-requested.jsonA verification/gracie-rollout/rollout.cjsA verification/gracie-rollout/startup-schema.jsonA verification/gracie-rollout/verification.jsonA verification/gracie-rollout/verify-failure.json
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 →