[object Object]

← back to Tk11438 Postgres Migration

Prepare verified Crezana socket rollout for scoped approval

25ead1ed8c86ff95711a4075482a1cb989e70782 · 2026-09-12 07:21:29 -0700 · Steve Abrams

Files touched

Diff

commit 25ead1ed8c86ff95711a4075482a1cb989e70782
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Sat Sep 12 07:21:29 2026 -0700

    Prepare verified Crezana socket rollout for scoped approval
---
 verification/crezana-proposal/APPROVAL.md          |  29 ++
 verification/crezana-proposal/baseline.json        | 362 +++++++++++++++++++++
 verification/crezana-proposal/readiness.cjs        |  36 ++
 verification/crezana-proposal/readiness.json       |  47 +++
 verification/crezana-proposal/refresh.py           |  35 ++
 .../crezana-proposal/vendor-requests.patch         |   5 +
 6 files changed, 514 insertions(+)

diff --git a/verification/crezana-proposal/APPROVAL.md b/verification/crezana-proposal/APPROVAL.md
new file mode 100644
index 0000000..39426ca
--- /dev/null
+++ b/verification/crezana-proposal/APPROVAL.md
@@ -0,0 +1,29 @@
+# TK-11438 — Crezana socket batch: approval required
+
+Prepared only. No source application, restart, canonical write or email send has occurred. Steve's latest report-in says keep unfinished/gated work open. The previous scoped approvals completed showroom, PatternDesignLab, Ken and Gracie; do not repeat those actions. The earlier broad relay covers already-described pending actions only; this new Crezana rollout is outside that scope.
+
+## Requested approval
+
+Apply the included one-line patch to /Users/macstudio3/Projects/crezana-internal/lib/vendor-requests.js, make a local commit, and restart only the existing PM2 crezana-internal process once. Its startup invokes existing CREATE TABLE IF NOT EXISTS and CREATE INDEX IF NOT EXISTS against dw_unified.vendor_requests. Approval must include these existing startup schema commands. Preserve all email exclusions: no request-creation, preview or sending endpoint and no email wrapper execution.
+
+The sole code change replaces the hardcoded host 127.0.0.1 with process.env.PGHOST || (process.platform === 'darwin' ? '/tmp' : '127.0.0.1'). Explicit host overrides and Linux fallback remain supported. No catalog/database-row update, DNS, remote deployment, public directory edit, credential change or PostgreSQL TCP shutdown is included.
+
+## Current baseline and evidence
+
+- Clean source HEAD 036e705f747943640d521747f41272ee30ae5a83; source SHA256 ce0099389bf08e01e2a7a08f2a1bf442e146cd0ea17500abd583bb93af840702. Prepared SHA256 d87ab5d2e4d44953aea64befe63c033dc0bc8479c3bc11fc5328c7bfb6d8690e; syntax PASS.
+- PM2 crezana-internal PID8192, restart count1, online, port10072. Effective and saved PGHOST=/tmp already; no PM2 env/dump edit or global pm2 save is needed.
+- Catalog API returns443 products. Six HTTP assertions passed: root missing/invalid401 and valid200; existing open catalog feed missing/valid200; health200. Preserve current auth boundaries and response hash. This task does not change Crezana's existing listener/exposure; Gracie's separate privacy changes remain untouched.
+- Independent pg clients with default_transaction_read_only=on verified TCP and socket resolve to dw_admin, dw_unified OID16391, same server start, 19columns/4indexes, and two Crezana requests (max id6). Schema/index hashes match. Missing socket fails ENOENT. No application module imported and no purchasing route invoked.
+- Fresh fleet scan: 15 prepared shared-module patches still unapplied, Gracie applied, no source drift. No conclusion that the remaining consumers are all migrated or inactive.
+
+## Execution prerequisites and rollback
+
+On approval, recheck source HEAD/hash, clean worktree, exact PM2 identity/PID and effective/saved host. Refresh read-only HTTP/catalog/schema/request baselines immediately before action. Back up the one source file and capture scoped PM2 metadata under a gitignored private directory (0700, files0600); check byte hash before replacement. Do not back up credentials in tracked files. Any concurrent drift stops execution for review.
+
+Apply only the exact one-line patch and syntax-check. Restart only crezana-internal once. Verify a new PID with restart count incremented once, stable health/auth/catalog hash and443 products, unchanged request rows/schema/indexes, no TCP5432 descriptors for the process, and successful socket startup schema completion before any authenticated request-list GET (that GET itself calls ensureSchema). Email-capable POSTs remain excluded. Record the actual checks and limits; do not call a skipped critical path done.
+
+On failure restore the exact source backup after checking no concurrent edits, and restart only this process to restore its original TCP behavior. Recheck health/auth/catalog; preserve all host/auth configuration. No PM2 global save, fleet restart or canonical data rollback. Restore only owned file changes. No automatic retirement or listener changes.
+
+## Status
+
+BLOCKED on Steve's approval of this concrete next rollout. TK-11438 stays open/incomplete; the session is not closed or compacted. Other remaining consumer and scheduler classification is preserved in verification/session-close/SESSION-HANDOFF.md. No new paid API work in this preparation.
diff --git a/verification/crezana-proposal/baseline.json b/verification/crezana-proposal/baseline.json
new file mode 100644
index 0000000..f5e5661
--- /dev/null
+++ b/verification/crezana-proposal/baseline.json
@@ -0,0 +1,362 @@
+{
+  "at": "2026-09-12T14:15:16.986454+00:00",
+  "scope": "Read-only source/runtime refresh and Crezana HTTP baseline; no module imports, requests API calls, DB writes, restarts or emails",
+  "modules": [
+    {
+      "project": "quadrille-internal",
+      "source": "/Users/macstudio3/Projects/quadrille-internal/lib/vendor-requests.js",
+      "sha256": "fd8e922c9ee816305b5df305c2f33ca738ab5da7834b8b14b188fc45e5e82f46",
+      "patch_state": "prepared-not-applied",
+      "head": "9dd52d38c202d086f0ca674da97ca69eb9e11a87",
+      "dirty_paths": [],
+      "runtime": [],
+      "saved": []
+    },
+    {
+      "project": "artmura-internal",
+      "source": "/Users/macstudio3/Projects/artmura-internal/lib/vendor-requests.js",
+      "sha256": "ce0099389bf08e01e2a7a08f2a1bf442e146cd0ea17500abd583bb93af840702",
+      "patch_state": "prepared-not-applied",
+      "head": "761694699d8ae5575f7b6ba4a8d68047bf7a52c0",
+      "dirty_paths": [],
+      "runtime": [],
+      "saved": []
+    },
+    {
+      "project": "astek-landing",
+      "source": "/Users/macstudio3/Projects/astek-landing/lib/vendor-requests.js",
+      "sha256": "fd8e922c9ee816305b5df305c2f33ca738ab5da7834b8b14b188fc45e5e82f46",
+      "patch_state": "prepared-not-applied",
+      "head": "9904c55aeb85fbeb43b4015ff7a07f43e1439344",
+      "dirty_paths": [
+        "?? scripts/run-data-refresh.sh"
+      ],
+      "runtime": [],
+      "saved": []
+    },
+    {
+      "project": "reidwitlin-landing",
+      "source": "/Users/macstudio3/Projects/reidwitlin-landing/lib/vendor-requests.js",
+      "sha256": "fd8e922c9ee816305b5df305c2f33ca738ab5da7834b8b14b188fc45e5e82f46",
+      "patch_state": "prepared-not-applied",
+      "head": "62165d78d4f806a7f3bbd206936c5636868e1131",
+      "dirty_paths": [],
+      "runtime": [
+        {
+          "name": "reidwitlin-landing",
+          "pid": 8291,
+          "status": "online",
+          "restarts": 1,
+          "env": {
+            "PORT": 9952
+          }
+        }
+      ],
+      "saved": [
+        {
+          "name": "reidwitlin-landing",
+          "env": {
+            "PORT": 9952
+          }
+        }
+      ]
+    },
+    {
+      "project": "zuber-internal",
+      "source": "/Users/macstudio3/Projects/zuber-internal/lib/vendor-requests.js",
+      "sha256": "ce0099389bf08e01e2a7a08f2a1bf442e146cd0ea17500abd583bb93af840702",
+      "patch_state": "prepared-not-applied",
+      "head": "3aa6743034ab28becd6b2869b4a57492a777fdc2",
+      "dirty_paths": [],
+      "runtime": [
+        {
+          "name": "zuber-internal",
+          "pid": 8273,
+          "status": "online",
+          "restarts": 1,
+          "env": {
+            "PORT": "10074"
+          }
+        }
+      ],
+      "saved": [
+        {
+          "name": "zuber-internal",
+          "env": {
+            "PORT": "10074"
+          }
+        }
+      ]
+    },
+    {
+      "project": "fabricut-internal",
+      "source": "/Users/macstudio3/Projects/fabricut-internal/lib/vendor-requests.js",
+      "sha256": "ce0099389bf08e01e2a7a08f2a1bf442e146cd0ea17500abd583bb93af840702",
+      "patch_state": "prepared-not-applied",
+      "head": "e79ebd6f3c730810406aec4675dbb2e8c69a6d04",
+      "dirty_paths": [],
+      "runtime": [],
+      "saved": []
+    },
+    {
+      "project": "crezana-internal",
+      "source": "/Users/macstudio3/Projects/crezana-internal/lib/vendor-requests.js",
+      "sha256": "ce0099389bf08e01e2a7a08f2a1bf442e146cd0ea17500abd583bb93af840702",
+      "patch_state": "prepared-not-applied",
+      "head": "036e705f747943640d521747f41272ee30ae5a83",
+      "dirty_paths": [],
+      "runtime": [
+        {
+          "name": "crezana-internal",
+          "pid": 8192,
+          "status": "online",
+          "restarts": 1,
+          "env": {
+            "PGHOST": "/tmp",
+            "PORT": "10072"
+          }
+        }
+      ],
+      "saved": [
+        {
+          "name": "crezana-internal",
+          "env": {
+            "PGHOST": "/tmp",
+            "PORT": "10072"
+          }
+        }
+      ]
+    },
+    {
+      "project": "fentucci-naturals",
+      "source": "/Users/macstudio3/Projects/fentucci-naturals/lib/vendor-requests.js",
+      "sha256": "ce0099389bf08e01e2a7a08f2a1bf442e146cd0ea17500abd583bb93af840702",
+      "patch_state": "prepared-not-applied",
+      "head": "09562bfdc36f67a06f671784992c43bdcd142a0c",
+      "dirty_paths": [],
+      "runtime": [],
+      "saved": []
+    },
+    {
+      "project": "fromental-internal",
+      "source": "/Users/macstudio3/Projects/fromental-internal/lib/vendor-requests.js",
+      "sha256": "ce0099389bf08e01e2a7a08f2a1bf442e146cd0ea17500abd583bb93af840702",
+      "patch_state": "prepared-not-applied",
+      "head": "ee8ee40e0da8f8a2c0c287f8a9ec5df492abcaf0",
+      "dirty_paths": [],
+      "runtime": [
+        {
+          "name": "fromental-internal",
+          "pid": 8298,
+          "status": "online",
+          "restarts": 1,
+          "env": {}
+        }
+      ],
+      "saved": [
+        {
+          "name": "fromental-internal",
+          "env": {}
+        }
+      ]
+    },
+    {
+      "project": "gracie-internal",
+      "source": "/Users/macstudio3/Projects/gracie-internal/lib/vendor-requests.js",
+      "sha256": "d87ab5d2e4d44953aea64befe63c033dc0bc8479c3bc11fc5328c7bfb6d8690e",
+      "patch_state": "applied",
+      "head": "bb7b548de6e52c5f5f065b5ea9589384ab0be850",
+      "dirty_paths": [],
+      "runtime": [
+        {
+          "name": "gracie-internal",
+          "pid": 91857,
+          "status": "online",
+          "restarts": 2,
+          "env": {
+            "PORT": "10073"
+          }
+        }
+      ],
+      "saved": [
+        {
+          "name": "gracie-internal",
+          "env": {
+            "PORT": "10073"
+          }
+        }
+      ]
+    },
+    {
+      "project": "fabricut-landing",
+      "source": "/Users/macstudio3/Projects/fabricut-landing/lib/vendor-requests.js",
+      "sha256": "ce0099389bf08e01e2a7a08f2a1bf442e146cd0ea17500abd583bb93af840702",
+      "patch_state": "prepared-not-applied",
+      "head": "468f0b067010fc3389c5819e910bbf175a980707",
+      "dirty_paths": [],
+      "runtime": [],
+      "saved": []
+    },
+    {
+      "project": "greenland-onboard",
+      "source": "/Users/macstudio3/Projects/greenland-onboard/lib/vendor-requests.js",
+      "sha256": "ce0099389bf08e01e2a7a08f2a1bf442e146cd0ea17500abd583bb93af840702",
+      "patch_state": "prepared-not-applied",
+      "head": "cc826bb073b453241a8c70f8b185a57f9d3974e1",
+      "dirty_paths": [],
+      "runtime": [
+        {
+          "name": "greenland-internal",
+          "pid": 85706,
+          "status": "online",
+          "restarts": 2,
+          "env": {}
+        }
+      ],
+      "saved": [
+        {
+          "name": "greenland-internal",
+          "env": {}
+        }
+      ]
+    },
+    {
+      "project": "schumacher-internal",
+      "source": "/Users/macstudio3/Projects/schumacher-internal/lib/vendor-requests.js",
+      "sha256": "ce0099389bf08e01e2a7a08f2a1bf442e146cd0ea17500abd583bb93af840702",
+      "patch_state": "prepared-not-applied",
+      "head": "967ddecffa4863fae764a913330202c50685cbe5",
+      "dirty_paths": [],
+      "runtime": [
+        {
+          "name": "schumacher-internal",
+          "pid": 8374,
+          "status": "online",
+          "restarts": 1,
+          "env": {
+            "PORT": "9946"
+          }
+        }
+      ],
+      "saved": [
+        {
+          "name": "schumacher-internal",
+          "env": {
+            "PORT": "9946"
+          }
+        }
+      ]
+    },
+    {
+      "project": "momentum-landing",
+      "source": "/Users/macstudio3/Projects/momentum-landing/lib/vendor-requests.js",
+      "sha256": "ce0099389bf08e01e2a7a08f2a1bf442e146cd0ea17500abd583bb93af840702",
+      "patch_state": "prepared-not-applied",
+      "head": "5ee2b91780cd39d61d5c996fbac0bf96252bb7aa",
+      "dirty_paths": [],
+      "runtime": [],
+      "saved": []
+    },
+    {
+      "project": "carnegie-internal",
+      "source": "/Users/macstudio3/Projects/carnegie-internal/lib/vendor-requests.js",
+      "sha256": "ce0099389bf08e01e2a7a08f2a1bf442e146cd0ea17500abd583bb93af840702",
+      "patch_state": "prepared-not-applied",
+      "head": "c3e2d2df5270d3ffccd04a4d8f460fbcea570432",
+      "dirty_paths": [],
+      "runtime": [],
+      "saved": []
+    },
+    {
+      "project": "muralsource-internal",
+      "source": "/Users/macstudio3/Projects/muralsource-internal/lib/vendor-requests.js",
+      "sha256": "ce0099389bf08e01e2a7a08f2a1bf442e146cd0ea17500abd583bb93af840702",
+      "patch_state": "prepared-not-applied",
+      "head": "4b375ee025592a661508377c8886648199f292e9",
+      "dirty_paths": [
+        "?? _look.mjs"
+      ],
+      "runtime": [
+        {
+          "name": "muralsource-internal",
+          "pid": 8416,
+          "status": "online",
+          "restarts": 1,
+          "env": {
+            "PORT": "9947"
+          }
+        }
+      ],
+      "saved": [
+        {
+          "name": "muralsource-internal",
+          "env": {
+            "PORT": "9947"
+          }
+        }
+      ]
+    }
+  ],
+  "crezana_http": [
+    {
+      "path": "/",
+      "auth": "missing",
+      "status": 401,
+      "expected": 401,
+      "pass": true,
+      "body_sha256": "0005d85116dc47ccae66cbbc7e55e4c72742ce598aca888d3b36c34ed7131318"
+    },
+    {
+      "path": "/",
+      "auth": "invalid",
+      "status": 401,
+      "expected": 401,
+      "pass": true,
+      "body_sha256": "0005d85116dc47ccae66cbbc7e55e4c72742ce598aca888d3b36c34ed7131318"
+    },
+    {
+      "path": "/",
+      "auth": "valid",
+      "status": 200,
+      "expected": 200,
+      "pass": true,
+      "body_sha256": "86e8596e35fb933ea615a79853a507ddd1a27a9467e1c80240abe4ec9b39398b"
+    },
+    {
+      "path": "/api/products",
+      "auth": "missing",
+      "status": 200,
+      "expected": 200,
+      "pass": true,
+      "body_sha256": "251485fcb22a421cfe948f67c32559f31005a905e1d1ca9c8984b5d6345465a9",
+      "response_shape": [
+        "count",
+        "products"
+      ],
+      "total": 443
+    },
+    {
+      "path": "/api/products",
+      "auth": "valid",
+      "status": 200,
+      "expected": 200,
+      "pass": true,
+      "body_sha256": "251485fcb22a421cfe948f67c32559f31005a905e1d1ca9c8984b5d6345465a9",
+      "response_shape": [
+        "count",
+        "products"
+      ],
+      "total": 443
+    },
+    {
+      "path": "/api/health",
+      "auth": "missing",
+      "status": 200,
+      "expected": 200,
+      "pass": true,
+      "body_sha256": "115726f12bcd3f61470ef8e624bf9538219201ffaf23097dac27cbca9c6d2796"
+    }
+  ],
+  "crezana_server_sha256": "201887d70f3836c4634e321ff147c577c7389693b95213e81fe4f6f024cebd63",
+  "all_http_pass": true
+}
diff --git a/verification/crezana-proposal/readiness.cjs b/verification/crezana-proposal/readiness.cjs
new file mode 100644
index 0000000..14575e9
--- /dev/null
+++ b/verification/crezana-proposal/readiness.cjs
@@ -0,0 +1,36 @@
+const fs=require('fs'),crypto=require('crypto'),cp=require('child_process');
+const root='/Users/macstudio3/Projects/crezana-internal';
+const {Client}=require(root+'/node_modules/pg');
+const raw=fs.readFileSync('/Users/macstudio3/Projects/secrets-manager/.env','utf8');
+const m=raw.match(/^DW_ADMIN_DB_PASSWORD=(.+)$/m);
+const password=process.env.DW_ADMIN_DB_PASSWORD||(m?m[1].replace(/^["']|["']$/g,'').trim():'');
+if(!password)throw Error('DB password unavailable');
+const sum=x=>crypto.createHash('sha256').update(x).digest('hex');
+async function read(host){
+ const c=new Client({host,port:5432,user:'dw_admin',database:'dw_unified',password,connectionTimeoutMillis:5000,options:'-c default_transaction_read_only=on',application_name:'tk11438-crezana-preflight'});
+ try{
+  await c.connect();
+  const id=(await c.query("SELECT current_user AS role, current_database() AS database, (SELECT oid FROM pg_database WHERE datname=current_database()) AS oid, pg_postmaster_start_time() AS server_start, inet_client_addr() IS NULL AS unix_socket, current_setting('default_transaction_read_only') AS readonly")).rows[0];
+  const schema=(await c.query("SELECT column_name,data_type,is_nullable FROM information_schema.columns WHERE table_schema='public' AND table_name='vendor_requests' ORDER BY ordinal_position")).rows;
+  const indexes=(await c.query("SELECT indexname,indexdef FROM pg_indexes WHERE schemaname='public' AND tablename='vendor_requests' ORDER BY indexname")).rows;
+  const rows=(await c.query("SELECT count(*)::int AS count,max(id)::text AS max_id FROM vendor_requests WHERE vendor_code='crezana'")).rows[0];
+  return {identity:id,columns:schema.length,indexes:indexes.length,schema_hash:sum(JSON.stringify(schema)),indexes_hash:sum(JSON.stringify(indexes)),requests:rows};
+ }finally{await c.end().catch(()=>{});}
+}
+(async()=>{
+ const tcp=await read('127.0.0.1'),socket=await read('/tmp');
+ for(const key of ['role','database','oid'])if(tcp.identity[key]!==socket.identity[key])throw Error('Identity mismatch '+key);
+ if(+tcp.identity.server_start!==+socket.identity.server_start)throw Error('Server mismatch');
+ if(tcp.identity.unix_socket||!socket.identity.unix_socket||socket.identity.readonly!=='on')throw Error('Transport/read-only mismatch');
+ if(tcp.schema_hash!==socket.schema_hash||tcp.indexes_hash!==socket.indexes_hash||JSON.stringify(tcp.requests)!==JSON.stringify(socket.requests))throw Error('Schema/request snapshot mismatch');
+ let missing;try{await read('/tmp/tk11438-nonexistent-socket');missing='UNEXPECTED_SUCCESS';}catch(e){missing=e.code;}
+ if(missing!=='ENOENT')throw Error('Missing socket failed differently: '+missing);
+ const source=fs.readFileSync(root+'/lib/vendor-requests.js','utf8');
+ const old="host: '127.0.0.1', port: 5432, user: 'dw_admin', database: 'dw_unified', password: PGPASS, max: 3";
+ const next="host: process.env.PGHOST || (process.platform === 'darwin' ? '/tmp' : '127.0.0.1'), port: 5432, user: 'dw_admin', database: 'dw_unified', password: PGPASS, max: 3";
+ if(source.split(old).length!==2)throw Error('Unexpected patch target');
+ const prepared=source.replace(old,next);fs.writeFileSync('/tmp/tk11438-crezana-prepared.cjs',prepared);
+ cp.execFileSync(process.execPath,['--check','/tmp/tk11438-crezana-prepared.cjs']);
+ const out={at:new Date().toISOString(),tcp,socket,missing_socket:missing,prepared_source_sha256:sum(prepared),source_sha256:sum(source),syntax:'PASS',applied:false,restarted:false,email_sends:0,scope:'Independent pg client SELECTs with default_transaction_read_only; prepared file syntax only; application module never imported'};
+ fs.writeFileSync('/tmp/tk11438-crezana-readiness.json',JSON.stringify(out,null,2)+'\n');console.log(JSON.stringify(out,null,2));
+})().catch(e=>{console.error(e.code||e.message);process.exitCode=1;});
diff --git a/verification/crezana-proposal/readiness.json b/verification/crezana-proposal/readiness.json
new file mode 100644
index 0000000..65d29ff
--- /dev/null
+++ b/verification/crezana-proposal/readiness.json
@@ -0,0 +1,47 @@
+{
+  "at": "2026-09-12T14:14:50.342Z",
+  "tcp": {
+    "identity": {
+      "role": "dw_admin",
+      "database": "dw_unified",
+      "oid": 16391,
+      "server_start": "2026-09-09T15:05:54.745Z",
+      "unix_socket": false,
+      "readonly": "on"
+    },
+    "columns": 19,
+    "indexes": 4,
+    "schema_hash": "8dd3158ce34c77c1d7177ac6e1edb658bf2c65ea7ba96a96f345dbfcd919fa0d",
+    "indexes_hash": "a04e8a1deafb32cc1210ae1c81a6b3509685fe53806dd4730ee767b1f2ab3a1d",
+    "requests": {
+      "count": 2,
+      "max_id": "6"
+    }
+  },
+  "socket": {
+    "identity": {
+      "role": "dw_admin",
+      "database": "dw_unified",
+      "oid": 16391,
+      "server_start": "2026-09-09T15:05:54.745Z",
+      "unix_socket": true,
+      "readonly": "on"
+    },
+    "columns": 19,
+    "indexes": 4,
+    "schema_hash": "8dd3158ce34c77c1d7177ac6e1edb658bf2c65ea7ba96a96f345dbfcd919fa0d",
+    "indexes_hash": "a04e8a1deafb32cc1210ae1c81a6b3509685fe53806dd4730ee767b1f2ab3a1d",
+    "requests": {
+      "count": 2,
+      "max_id": "6"
+    }
+  },
+  "missing_socket": "ENOENT",
+  "prepared_source_sha256": "d87ab5d2e4d44953aea64befe63c033dc0bc8479c3bc11fc5328c7bfb6d8690e",
+  "source_sha256": "ce0099389bf08e01e2a7a08f2a1bf442e146cd0ea17500abd583bb93af840702",
+  "syntax": "PASS",
+  "applied": false,
+  "restarted": false,
+  "email_sends": 0,
+  "scope": "Independent pg client SELECTs with default_transaction_read_only; prepared file syntax only; application module never imported"
+}
diff --git a/verification/crezana-proposal/refresh.py b/verification/crezana-proposal/refresh.py
new file mode 100644
index 0000000..103b169
--- /dev/null
+++ b/verification/crezana-proposal/refresh.py
@@ -0,0 +1,35 @@
+import pathlib,json,hashlib,subprocess,datetime,urllib.request,urllib.error,base64,re
+base=pathlib.Path('/Users/macstudio3/Projects/tk11438-postgres-migration')
+ledger=json.loads((base/'verification/fleet-classification/patch-manifest.json').read_text())
+raw=subprocess.check_output(['pm2','jlist'],text=True,timeout=30)
+live=json.loads(raw[raw.index('['):])
+saved=json.loads(pathlib.Path('/Users/macstudio3/.pm2/dump.pm2').read_text())
+def safe(env):
+ return {k:env[k] for k in ['PGHOST','PGPORT','PGDATABASE','PGUSER','PORT','DATA_SOURCE'] if k in env}
+results=[]
+for m in ledger['modules']:
+ p=pathlib.Path(m['path']);root=p.parent.parent
+ h=hashlib.sha256(p.read_bytes()).hexdigest()
+ matches=[a for a in live if a.get('pm2_env',{}).get('pm_cwd')==str(root)]
+ names=[a['name'] for a in matches]
+ results.append({'project':m['project'],'source':str(p),'sha256':h,'patch_state':'prepared-not-applied' if h==m['before_sha256'] else 'applied' if h==m['after_sha256'] else 'drift-review-required','head':subprocess.check_output(['git','rev-parse','HEAD'],cwd=root,text=True).strip(),'dirty_paths':subprocess.check_output(['git','status','--porcelain'],cwd=root,text=True).splitlines(),'runtime':[{'name':a['name'],'pid':a['pid'],'status':a['pm2_env'].get('status'),'restarts':a['pm2_env'].get('restart_time'),'env':safe(a['pm2_env'])} for a in matches],'saved':[{'name':a['name'],'env':safe(a)} for a in saved if a.get('name') in names]})
+crezana=next(r for r in results if r['project']=='crezana-internal')
+server=pathlib.Path('/Users/macstudio3/Projects/crezana-internal/server.js').read_text()
+user=re.search(r"cred\.name !== '([^']+)'",server).group(1)
+password=re.search(r"cred\.pass !== '([^']+)'",server).group(1)
+auth='Basic '+base64.b64encode((user+':'+password).encode()).decode()
+checks=[]
+for path,mode,expected in [('/', 'missing',401),('/','invalid',401),('/','valid',200),('/api/products','missing',200),('/api/products','valid',200),('/api/health','missing',200)]:
+ headers={} if mode=='missing' else {'Authorization':auth if mode=='valid' else 'Basic aW52YWxpZDppbnZhbGlk'}
+ req=urllib.request.Request('http://127.0.0.1:10072'+path,headers=headers)
+ try:
+  with urllib.request.urlopen(req,timeout=15) as response: status=response.status;body=response.read()
+ except urllib.error.HTTPError as e: status=e.code;body=e.read()
+ item={'path':path,'auth':mode,'status':status,'expected':expected,'pass':status==expected,'body_sha256':hashlib.sha256(body).hexdigest()}
+ if path=='/api/products' and status==200:
+  data=json.loads(body);item['response_shape']=list(data) if isinstance(data,dict) else 'array'
+  item['total']=data.get('total',data.get('count')) if isinstance(data,dict) else len(data)
+ checks.append(item)
+out={'at':datetime.datetime.now(datetime.timezone.utc).isoformat(),'scope':'Read-only source/runtime refresh and Crezana HTTP baseline; no module imports, requests API calls, DB writes, restarts or emails','modules':results,'crezana_http':checks,'crezana_server_sha256':hashlib.sha256(server.encode()).hexdigest(),'all_http_pass':all(x['pass'] for x in checks)}
+pathlib.Path('/tmp/tk11438-resume-preflight.json').write_text(json.dumps(out,indent=2)+'\n')
+print(json.dumps({'states':{s:sum(r['patch_state']==s for r in results) for s in {r['patch_state'] for r in results}},'crezana':crezana,'http':checks},indent=2))
diff --git a/verification/crezana-proposal/vendor-requests.patch b/verification/crezana-proposal/vendor-requests.patch
new file mode 100644
index 0000000..c21cfba
--- /dev/null
+++ b/verification/crezana-proposal/vendor-requests.patch
@@ -0,0 +1,5 @@
+--- a/lib/vendor-requests.js
++++ b/lib/vendor-requests.js
+@@ -52 +52 @@
+-  if (!pool) pool = new Pool({ host: '127.0.0.1', port: 5432, user: 'dw_admin', database: 'dw_unified', password: PGPASS, max: 3 });
++  if (!pool) pool = new Pool({ host: process.env.PGHOST || (process.platform === 'darwin' ? '/tmp' : '127.0.0.1'), port: 5432, user: 'dw_admin', database: 'dw_unified', password: PGPASS, max: 3 });

← 7dd2703 Save session closeout and remaining PostgreSQL migration han  ·  back to Tk11438 Postgres Migration  ·  TK-11438: residual sweep restore map — 8 local fallback/env 34e2124 →