{
  "info": {
    "name": "NSO Ingest Webhook",
    "description": "Test the NSO signed ingest webhook end-to-end and verify upserts against Supabase without writing curl commands. Set the collection variables NSO_WEBHOOK_HOST, NSO_TENANT_SLUG, NSO_HMAC_SECRET, SUPABASE_URL, and SUPABASE_SERVICE_ROLE_KEY before running.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "event": [
    {
      "listen": "prerequest",
      "script": {
        "type": "text/javascript",
        "exec": [
          "// Collection-level pre-request script.",
          "// Auto-signs any POST that has a raw JSON body using NSO_HMAC_SECRET,",
          "// then sets the exact `x-nso-signature` and `x-nso-timestamp` headers the webhook expects.",
          "// Skips GETs and requests without a raw body (e.g. Supabase verify calls).",
          "try {",
          "  const method = (pm.request.method || '').toUpperCase();",
          "  const rawBody = pm.request.body && pm.request.body.raw;",
          "  if (method !== 'POST' || !rawBody) { return; }",
          "  // Requests that intentionally send a wrong/preset signature or timestamp opt out",
          "  // by setting SKIP_AUTO_SIGN=true in their own pre-request script.",
          "  const skip = pm.variables.get('SKIP_AUTO_SIGN');",
          "  if (skip === true || skip === 'true') {",
          "    pm.variables.set('SKIP_AUTO_SIGN', 'false');",
          "    return;",
          "  }",
          "  const secret = pm.variables.get('NSO_HMAC_SECRET') || pm.environment.get('NSO_HMAC_SECRET');",
          "  if (!secret) { console.warn('NSO_HMAC_SECRET is not set; skipping auto-sign.'); return; }",
          "  // Resolve {{...}} references in the raw body before signing so the",
          "  // bytes we hash match exactly what Postman puts on the wire.",
          "  const resolved = pm.variables.replaceIn(rawBody);",
          "  const signature = CryptoJS.HmacSHA256(resolved, secret).toString(CryptoJS.enc.Hex);",
          "  pm.request.headers.upsert({ key: 'content-type', value: 'application/json' });",
          "  pm.request.headers.upsert({ key: 'x-nso-signature', value: signature });",
          "  // Only add a timestamp if the request did not already provide one (e.g. stale/future tests).",
          "  if (!pm.request.headers.get('x-nso-timestamp')) {",
          "    pm.request.headers.upsert({ key: 'x-nso-timestamp', value: new Date().toISOString() });",
          "  }",
          "  // Expose the resolved body/signature to request-level scripts if needed.",
          "  pm.variables.set('SIGNED_BODY', resolved);",
          "  pm.variables.set('SIGNATURE', signature);",
          "} catch (err) {",
          "  console.error('Auto-sign pre-request failed:', err);",
          "}"
        ]
      }
    }
  ],
  "variable": [
    {
      "key": "NSO_WEBHOOK_HOST",
      "value": "https://nso.jackiepoole.com"
    },
    {
      "key": "NSO_TENANT_SLUG",
      "value": "your-tenant-slug"
    },
    {
      "key": "NSO_HMAC_SECRET",
      "value": "your-tenant-hmac-secret"
    },
    {
      "key": "SUPABASE_URL",
      "value": "https://YOUR-PROJECT.supabase.co"
    },
    {
      "key": "SUPABASE_SERVICE_ROLE_KEY",
      "value": "service-role-key"
    },
    {
      "key": "FINGERPRINT",
      "value": "postman-smoke:example.com:e2e-1"
    },
    {
      "key": "BAD_FINGERPRINT",
      "value": "postman-smoke:example.com:bad-sig-1"
    },
    {
      "key": "BAD_SIG_ONLY_FINGERPRINT",
      "value": "postman-smoke:example.com:bad-sig-only-1"
    },
    {
      "key": "HAPPY_FINGERPRINT",
      "value": "postman-smoke:example.com:happy-1"
    },
    {
      "key": "IDEMPOTENT_FINGERPRINT",
      "value": "postman-smoke:example.com:idempotent-1"
    },
    {
      "key": "MISSING_SIG_FINGERPRINT",
      "value": "postman-smoke:example.com:missing-sig-1"
    },
    {
      "key": "STALE_TS_FINGERPRINT",
      "value": "postman-smoke:example.com:stale-ts-1"
    },
    {
      "key": "NO_TS_FINGERPRINT",
      "value": "postman-smoke:example.com:no-ts-1"
    },
    {
      "key": "MISSING_FIELD_FINGERPRINT",
      "value": "postman-smoke:example.com:missing-field-1"
    },
    {
      "key": "INVALID_HMAC_FINGERPRINT",
      "value": "postman-smoke:example.com:invalid-hmac-1"
    },
    {
      "key": "OMIT_SIG_FINGERPRINT",
      "value": "postman-smoke:example.com:omit-sig-1"
    },
    {
      "key": "NO_SIG_FINGERPRINT",
      "value": "postman-smoke:example.com:no-sig-20"
    },
    {
      "key": "DIFFERENT_SECRET_FINGERPRINT",
      "value": "postman-smoke:example.com:different-secret-1"
    },
    {
      "key": "EXPIRED_TS_FINGERPRINT",
      "value": "postman-smoke:example.com:expired-ts-23"
    },
    {
      "key": "FUTURE_TS_FINGERPRINT",
      "value": "postman-smoke:example.com:future-ts-24"
    },
    {
      "key": "OMIT_TS_FINGERPRINT",
      "value": "postman-smoke:example.com:omit-ts-25"
    },
    {
      "key": "BEYOND_SKEW_FINGERPRINT",
      "value": "postman-smoke:example.com:beyond-skew-26"
    },
    {
      "key": "VALID_SKEW_FINGERPRINT",
      "value": "postman-smoke:example.com:valid-skew-27"
    },
    {
      "key": "INVALID_SIG_VALID_TS_FINGERPRINT",
      "value": "postman-smoke:example.com:invalid-sig-valid-ts-28"
    },
    {
      "key": "MISSING_SIG_VALID_TS_FINGERPRINT",
      "value": "postman-smoke:example.com:missing-sig-valid-ts-29"
    },
    {
      "key": "OLDER_THAN_5MIN_FINGERPRINT",
      "value": "postman-smoke:example.com:older-than-5min-30"
    },
    {
      "key": "CURRENT_TS_SUCCESS_FINGERPRINT",
      "value": "postman-smoke:example.com:current-ts-success-31"
    },
    {
      "key": "CURRENT_INVALID_SIG_FINGERPRINT",
      "value": "postman-smoke:example.com:current-invalid-sig-32"
    },
    {
      "key": "OMIT_SIG_VALID_TS_FINGERPRINT",
      "value": "postman-smoke:example.com:omit-sig-valid-ts-33"
    },
    {
      "key": "OMIT_TS_VALID_SIG_FINGERPRINT",
      "value": "postman-smoke:example.com:omit-ts-valid-sig-34"
    },
    {
      "key": "INVALID_TS_FORMAT_FINGERPRINT",
      "value": "postman-smoke:example.com:invalid-ts-format-35"
    },
    {
      "key": "INCORRECT_SECRET_FINGERPRINT",
      "value": "postman-smoke:example.com:incorrect-secret-36"
    },
    {
      "key": "MODIFIED_BODY_FINGERPRINT",
      "value": "postman-smoke:example.com:modified-body-37"
    },
    {
      "key": "REPLAY_NONCE_FINGERPRINT",
      "value": "postman-smoke:example.com:replay-nonce-38"
    },
    {
      "key": "OMIT_SIG_EXACT_FINGERPRINT",
      "value": "postman-smoke:example.com:omit-sig-exact-39"
    },
    {
      "key": "OMIT_TS_EXACT_FINGERPRINT",
      "value": "postman-smoke:example.com:omit-ts-exact-40"
    },
    {
      "key": "WRONG_SIG_VALID_BODY_TS_FINGERPRINT",
      "value": "postman-smoke:example.com:wrong-sig-valid-body-ts-41"
    },
    {
      "key": "VALID_SIG_TS_MODIFIED_BODY_FINGERPRINT",
      "value": "postman-smoke:example.com:valid-sig-ts-modified-body-42"
    },
    {
      "key": "VALID_FULL_SUCCESS_FINGERPRINT",
      "value": "postman-smoke:example.com:valid-full-success-43"
    },
    {
      "key": "EXPIRED_TS_EXACT_FINGERPRINT",
      "value": "postman-smoke:example.com:expired-ts-exact-44"
    }
  ],
  "item": [
    {
      "name": "1. POST signed ingest",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman smoke test',",
              "    severity: 'low',",
              "    fingerprint: pm.variables.get('FINGERPRINT'),",
              "    description: 'Sent from the Postman collection walkthrough.',",
              "    remediation: 'No action required.'",
              "  }]",
              "};",
              "const body = JSON.stringify(payload);",
              "const secret = pm.variables.get('NSO_HMAC_SECRET');",
              "const sig = CryptoJS.HmacSHA256(body, secret).toString(CryptoJS.enc.Hex);",
              "pm.variables.set('SIGNED_BODY', body);",
              "pm.variables.set('SIGNATURE', sig);"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('200 OK', () => pm.response.to.have.status(200));",
              "pm.test('ok:true', () => pm.expect(pm.response.json().ok).to.eql(true));"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-signature",
            "value": "{{SIGNATURE}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{SIGNED_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "2. Verify row in Supabase",
      "event": [
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('200 OK', () => pm.response.to.have.status(200));",
              "const rows = pm.response.json();",
              "pm.test('one row', () => pm.expect(rows.length).to.eql(1));",
              "pm.test('matches fingerprint', () => pm.expect(rows[0].fingerprint).to.eql(pm.variables.get('FINGERPRINT')));"
            ]
          }
        }
      ],
      "request": {
        "method": "GET",
        "header": [
          {
            "key": "apikey",
            "value": "{{SUPABASE_SERVICE_ROLE_KEY}}"
          },
          {
            "key": "Authorization",
            "value": "Bearer {{SUPABASE_SERVICE_ROLE_KEY}}"
          }
        ],
        "url": {
          "raw": "{{SUPABASE_URL}}/rest/v1/findings?fingerprint=eq.{{FINGERPRINT}}",
          "host": [
            "{{SUPABASE_URL}}"
          ],
          "path": [
            "rest",
            "v1",
            "findings"
          ],
          "query": [
            {
              "key": "fingerprint",
              "value": "eq.{{FINGERPRINT}}"
            }
          ]
        }
      }
    },
    {
      "name": "3. Re-send to confirm idempotency",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "const body = pm.variables.get('SIGNED_BODY');",
              "const secret = pm.variables.get('NSO_HMAC_SECRET');",
              "if (!body) { throw new Error('Run request 1 first to populate SIGNED_BODY.'); }",
              "const sig = CryptoJS.HmacSHA256(body, secret).toString(CryptoJS.enc.Hex);",
              "pm.variables.set('SIGNATURE', sig);"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('200 OK', () => pm.response.to.have.status(200));",
              "pm.test('upsert path', () => pm.expect(pm.response.json().inserted).to.be.oneOf([0, 1]));"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-signature",
            "value": "{{SIGNATURE}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{SIGNED_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "4. POST with bad signature (expect 401)",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman bad-signature test',",
              "    severity: 'low',",
              "    fingerprint: pm.variables.get('BAD_FINGERPRINT'),",
              "    description: 'Sent with an intentionally invalid HMAC signature.',",
              "    remediation: 'Should be rejected before insert.'",
              "  }]",
              "};",
              "const body = JSON.stringify(payload);",
              "// Sign with the WRONG secret so the server-side HMAC check fails.",
              "const badSig = CryptoJS.HmacSHA256(body, 'this-is-not-the-real-secret')",
              "  .toString(CryptoJS.enc.Hex);",
              "pm.variables.set('BAD_SIGNED_BODY', body);",
              "pm.variables.set('BAD_SIGNATURE', badSig);",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');",
              "pm.variables.set('VALID_TS_HEADER', new Date().toISOString());"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('rejected (401/403)', () => pm.expect(pm.response.code).to.be.oneOf([401, 403]));",
              "pm.test('no ok:true in body', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* non-JSON error body is fine */ }",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-signature",
            "value": "{{BAD_SIGNATURE}}"
          },
          {
            "key": "x-nso-timestamp",
            "value": "{{VALID_TS_HEADER}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{BAD_SIGNED_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "5. Verify NO row was inserted for bad signature",
      "event": [
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('200 OK', () => pm.response.to.have.status(200));",
              "const rows = pm.response.json();",
              "pm.test('zero rows for bad fingerprint', () => pm.expect(rows.length).to.eql(0));"
            ]
          }
        }
      ],
      "request": {
        "method": "GET",
        "header": [
          {
            "key": "apikey",
            "value": "{{SUPABASE_SERVICE_ROLE_KEY}}"
          },
          {
            "key": "Authorization",
            "value": "Bearer {{SUPABASE_SERVICE_ROLE_KEY}}"
          }
        ],
        "url": {
          "raw": "{{SUPABASE_URL}}/rest/v1/findings?fingerprint=eq.{{BAD_FINGERPRINT}}",
          "host": [
            "{{SUPABASE_URL}}"
          ],
          "path": [
            "rest",
            "v1",
            "findings"
          ],
          "query": [
            {
              "key": "fingerprint",
              "value": "eq.{{BAD_FINGERPRINT}}"
            }
          ]
        }
      }
    },
    {
      "name": "6. Happy-path: signed POST + verify insert",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman happy-path signed insert',",
              "    severity: 'low',",
              "    fingerprint: pm.variables.get('HAPPY_FINGERPRINT'),",
              "    description: 'Signed with the real HMAC secret; should insert exactly one row.',",
              "    remediation: 'No action required.'",
              "  }]",
              "};",
              "const body = JSON.stringify(payload);",
              "const sig = CryptoJS.HmacSHA256(body, pm.variables.get('NSO_HMAC_SECRET'))",
              "  .toString(CryptoJS.enc.Hex);",
              "pm.variables.set('HAPPY_SIGNED_BODY', body);",
              "pm.variables.set('HAPPY_SIGNATURE', sig);"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook 200 OK', () => pm.response.to.have.status(200));",
              "const body = pm.response.json();",
              "pm.test('ok:true', () => pm.expect(body.ok).to.eql(true));",
              "pm.test('inserted >= 1', () => pm.expect(body.inserted).to.be.at.least(1));",
              "",
              "// Chained verification: query Supabase for the just-inserted row.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('HAPPY_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('exactly one row inserted', () => pm.expect(rows.length).to.eql(1));",
              "  pm.test('row fingerprint matches', () => pm.expect(rows[0].fingerprint).to.eql(fp));",
              "  pm.test('row title matches', () => pm.expect(rows[0].title).to.eql('Postman happy-path signed insert'));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-signature",
            "value": "{{HAPPY_SIGNATURE}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{HAPPY_SIGNED_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "7. Send twice and assert no duplicate rows",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman idempotency test',",
              "    severity: 'low',",
              "    fingerprint: pm.variables.get('IDEMPOTENT_FINGERPRINT'),",
              "    description: 'Signed twice to verify upsert deduplication.',",
              "    remediation: 'No action required.'",
              "  }]",
              "};",
              "const body = JSON.stringify(payload);",
              "const sig = CryptoJS.HmacSHA256(body, pm.variables.get('NSO_HMAC_SECRET'))",
              "  .toString(CryptoJS.enc.Hex);",
              "pm.variables.set('IDEMPOTENT_SIGNED_BODY', body);",
              "pm.variables.set('IDEMPOTENT_SIGNATURE', sig);"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('first POST 200 OK', () => pm.response.to.have.status(200));",
              "const firstBody = pm.response.json();",
              "pm.test('first ok:true', () => pm.expect(firstBody.ok).to.eql(true));",
              "pm.test('first inserted >= 1', () => pm.expect(firstBody.inserted).to.be.at.least(1));",
              "",
              "// Send the exact same payload a second time to prove upsert idempotency.",
              "const host = pm.variables.get('NSO_WEBHOOK_HOST');",
              "const slug = pm.variables.get('NSO_TENANT_SLUG');",
              "const body = pm.variables.get('IDEMPOTENT_SIGNED_BODY');",
              "const secret = pm.variables.get('NSO_HMAC_SECRET');",
              "const secondSig = CryptoJS.HmacSHA256(body, secret).toString(CryptoJS.enc.Hex);",
              "pm.sendRequest({",
              "  url: `${host}/api/public/ingest/${slug}`,",
              "  method: 'POST',",
              "  header: { 'content-type': 'application/json', 'x-nso-signature': secondSig },",
              "  body: { mode: 'raw', raw: body }",
              "}, (err, res) => {",
              "  pm.test('second POST 200 OK', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const secondBody = res.json();",
              "  pm.test('second ok:true', () => pm.expect(secondBody.ok).to.eql(true));",
              "  pm.test('second inserted is idempotent (0 or 1)', () => pm.expect(secondBody.inserted).to.be.oneOf([0, 1]));",
              "",
              "  // Verify the database still has exactly one row for this fingerprint.",
              "  const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "  const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "  const fp = pm.variables.get('IDEMPOTENT_FINGERPRINT');",
              "  pm.sendRequest({",
              "    url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "    method: 'GET',",
              "    header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "  }, (err2, res2) => {",
              "    pm.test('supabase lookup 200', () => {",
              "      pm.expect(err2).to.be.null;",
              "      pm.expect(res2.code).to.eql(200);",
              "    });",
              "    const rows = res2.json();",
              "    pm.test('exactly one row after two sends', () => pm.expect(rows.length).to.eql(1));",
              "    pm.test('fingerprint matches', () => pm.expect(rows[0].fingerprint).to.eql(fp));",
              "  });",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-signature",
            "value": "{{IDEMPOTENT_SIGNATURE}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{IDEMPOTENT_SIGNED_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "8. Reject wrong signature + assert no insert (single request)",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build a payload and sign it with the WRONG secret so the server-side",
              "// HMAC check must fail. Overrides the collection-level auto-signer by",
              "// setting `x-nso-signature` explicitly from BAD_ONLY_SIGNATURE.",
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman wrong-signature rejection test',",
              "    severity: 'low',",
              "    fingerprint: pm.variables.get('BAD_SIG_ONLY_FINGERPRINT'),",
              "    description: 'Signed with an intentionally wrong HMAC secret.',",
              "    remediation: 'Should be rejected before insert.'",
              "  }]",
              "};",
              "const body = JSON.stringify(payload);",
              "const badSig = CryptoJS.HmacSHA256(body, 'definitely-not-the-real-secret')",
              "  .toString(CryptoJS.enc.Hex);",
              "pm.variables.set('BAD_ONLY_SIGNED_BODY', body);",
              "pm.variables.set('BAD_ONLY_SIGNATURE', badSig);",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');",
              "pm.variables.set('VALID_TS_HEADER', new Date().toISOString());"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook rejects with auth error (401/403)', () => {",
              "  pm.expect(pm.response.code).to.be.oneOf([401, 403]);",
              "});",
              "pm.test('response is not ok:true', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* non-JSON body is fine */ }",
              "});",
              "",
              "// Chained verification: confirm no row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('BAD_SIG_ONLY_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('zero rows inserted for rejected signature', () => pm.expect(rows.length).to.eql(0));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-signature",
            "value": "{{BAD_ONLY_SIGNATURE}}"
          },
          {
            "key": "x-nso-timestamp",
            "value": "{{VALID_TS_HEADER}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{BAD_ONLY_SIGNED_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "9. Reject missing signature header + assert no insert",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build a payload but intentionally do NOT set x-nso-signature.",
              "// SKIP_AUTO_SIGN prevents the collection-level signer from adding it.",
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman missing-signature rejection test',",
              "    severity: 'low',",
              "    fingerprint: pm.variables.get('MISSING_SIG_FINGERPRINT'),",
              "    description: 'Sent without the required HMAC signature header.',",
              "    remediation: 'Should be rejected before insert.'",
              "  }]",
              "};",
              "const body = JSON.stringify(payload);",
              "pm.variables.set('MISSING_SIG_BODY', body);",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');",
              "pm.variables.set('VALID_TS_HEADER', new Date().toISOString());"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook rejects with auth error (401/403)', () => {",
              "  pm.expect(pm.response.code).to.be.oneOf([401, 403]);",
              "});",
              "pm.test('response is not ok:true', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* non-JSON error body is fine */ }",
              "});",
              "",
              "// Chained verification: confirm no row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('MISSING_SIG_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('zero rows inserted for missing signature', () => pm.expect(rows.length).to.eql(0));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-timestamp",
            "value": "{{VALID_TS_HEADER}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{MISSING_SIG_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "10. Reject stale timestamp header + assert no insert",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build payload, let the collection-level script auto-sign the body,",
              "// but attach an x-nso-timestamp header that is well outside the 5 min window.",
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman stale-timestamp rejection test',",
              "    severity: 'low',",
              "    fingerprint: pm.variables.get('STALE_TS_FINGERPRINT'),",
              "    description: 'Valid signature over the body, but timestamp is 1 hour old.',",
              "    remediation: 'Should be rejected before insert.'",
              "  }]",
              "};",
              "pm.variables.set('STALE_TS_BODY', JSON.stringify(payload));",
              "// 1 hour in the past \u2014 well beyond the 5 minute replay window.",
              "const staleIso = new Date(Date.now() - 60 * 60 * 1000).toISOString();",
              "pm.request.headers.upsert({ key: 'x-nso-timestamp', value: staleIso });"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook rejects stale timestamp with auth error (401/403)', () => {",
              "  pm.expect(pm.response.code).to.be.oneOf([401, 403]);",
              "});",
              "pm.test('response is not ok:true', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* non-JSON error body is fine */ }",
              "});",
              "",
              "// Chained verification: confirm no row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('STALE_TS_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('zero rows inserted for stale timestamp', () => pm.expect(rows.length).to.eql(0));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{STALE_TS_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "12. Reject payload missing required field (expect 400)",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build a payload that is validly signed but omits the required `title`",
              "// field on the finding. The collection-level pre-request script will",
              "// still sign the exact bytes we send, so signature verification passes",
              "// and the server must reject on schema validation (400).",
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    // title intentionally omitted",
              "    severity: 'low',",
              "    fingerprint: pm.variables.get('MISSING_FIELD_FINGERPRINT'),",
              "    description: 'Missing required `title` field to trigger schema rejection.',",
              "    remediation: 'Should be rejected with 400.'",
              "  }]",
              "};",
              "pm.variables.set('MISSING_FIELD_BODY', JSON.stringify(payload));"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook rejects invalid payload with 400', () => pm.response.to.have.status(400));",
              "pm.test('response is not ok:true', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* non-JSON error body is fine */ }",
              "});",
              "",
              "// Chained verification: confirm no row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('MISSING_FIELD_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('zero rows inserted for invalid payload', () => pm.expect(rows.length).to.eql(0));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{MISSING_FIELD_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "13. Fully valid payload + valid signature (expect 200 + row inserted)",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Uses the collection-level auto-signer. Build a complete, valid payload.",
              "const fp = 'postman-full-valid-' + Date.now();",
              "pm.variables.set('FULL_VALID_FINGERPRINT', fp);",
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman fully valid signed insert',",
              "    severity: 'medium',",
              "    fingerprint: fp,",
              "    description: 'All required fields present; signed with the real HMAC secret.',",
              "    remediation: 'No action required.'",
              "  }]",
              "};",
              "pm.variables.set('FULL_VALID_BODY', JSON.stringify(payload));"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook 200 OK', () => pm.response.to.have.status(200));",
              "const body = pm.response.json();",
              "pm.test('ok:true', () => pm.expect(body.ok).to.eql(true));",
              "pm.test('inserted >= 1', () => pm.expect(body.inserted).to.be.at.least(1));",
              "",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('FULL_VALID_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('exactly one row inserted', () => pm.expect(rows.length).to.eql(1));",
              "  pm.test('row title matches', () => pm.expect(rows[0].title).to.eql('Postman fully valid signed insert'));",
              "  pm.test('row severity matches', () => pm.expect(rows[0].severity).to.eql('medium'));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{FULL_VALID_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "14. Reject malformed HMAC signature + assert no insert",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build a valid payload but attach a clearly malformed x-nso-signature.",
              "// SKIP_AUTO_SIGN prevents the collection-level signer from replacing it.",
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman malformed HMAC rejection test',",
              "    severity: 'low',",
              "    fingerprint: pm.variables.get('INVALID_HMAC_FINGERPRINT'),",
              "    description: 'Sent with a non-hex, malformed HMAC signature.',",
              "    remediation: 'Should be rejected before insert.'",
              "  }]",
              "};",
              "pm.variables.set('INVALID_HMAC_BODY', JSON.stringify(payload));",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');",
              "pm.variables.set('VALID_TS_HEADER', new Date().toISOString());"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook rejects malformed signature with auth error (401/403)', () => {",
              "  pm.expect(pm.response.code).to.be.oneOf([401, 403]);",
              "});",
              "pm.test('response is not ok:true', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* non-JSON error body is fine */ }",
              "});",
              "",
              "// Chained verification: confirm no row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('INVALID_HMAC_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('zero rows inserted for malformed signature', () => pm.expect(rows.length).to.eql(0));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-signature",
            "value": "notavalidhmacsignature"
          },
          {
            "key": "x-nso-timestamp",
            "value": "{{VALID_TS_HEADER}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{INVALID_HMAC_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "15. Omit x-nso-signature header + assert no insert",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build a valid payload but explicitly omit the x-nso-signature header.",
              "// SKIP_AUTO_SIGN prevents the collection-level signer from adding it.",
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman omit-signature rejection test',",
              "    severity: 'low',",
              "    fingerprint: pm.variables.get('OMIT_SIG_FINGERPRINT'),",
              "    description: 'Sent without the x-nso-signature header entirely.',",
              "    remediation: 'Should be rejected before insert.'",
              "  }]",
              "};",
              "const body = JSON.stringify(payload);",
              "pm.variables.set('OMIT_SIG_BODY', body);",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');",
              "pm.variables.set('VALID_TS_HEADER', new Date().toISOString());"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook rejects missing signature with auth error (401/403)', () => {",
              "  pm.expect(pm.response.code).to.be.oneOf([401, 403]);",
              "});",
              "pm.test('response is not ok:true', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* non-JSON body is fine */ }",
              "});",
              "",
              "// Chained verification: confirm no row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('OMIT_SIG_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('zero rows inserted when signature header is omitted', () => pm.expect(rows.length).to.eql(0));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-timestamp",
            "value": "{{VALID_TS_HEADER}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{OMIT_SIG_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "16. Reject payload signed with different secret + assert no insert",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build a valid payload but sign it with a DIFFERENT secret than the one",
              "// configured for this tenant. The signature itself is a valid HMAC, but",
              "// it will not match the secret the server uses for verification.",
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman different-secret rejection test',",
              "    severity: 'low',",
              "    fingerprint: pm.variables.get('DIFFERENT_SECRET_FINGERPRINT'),",
              "    description: 'Signed with a different, unrelated HMAC secret.',",
              "    remediation: 'Should be rejected before insert.'",
              "  }]",
              "};",
              "const body = JSON.stringify(payload);",
              "const differentSecret = 'a-completely-different-secret-that-is-not-the-tenant-secret';",
              "const differentSig = CryptoJS.HmacSHA256(body, differentSecret)",
              "  .toString(CryptoJS.enc.Hex);",
              "pm.variables.set('DIFFERENT_SECRET_BODY', body);",
              "pm.variables.set('DIFFERENT_SECRET_SIGNATURE', differentSig);",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');",
              "pm.variables.set('VALID_TS_HEADER', new Date().toISOString());"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook rejects different-secret signature with auth error (401/403)', () => {",
              "  pm.expect(pm.response.code).to.be.oneOf([401, 403]);",
              "});",
              "pm.test('response is not ok:true', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* non-JSON error body is fine */ }",
              "});",
              "",
              "// Chained verification: confirm no row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('DIFFERENT_SECRET_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('zero rows inserted for different-secret signature', () => pm.expect(rows.length).to.eql(0));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-signature",
            "value": "{{DIFFERENT_SECRET_SIGNATURE}}"
          },
          {
            "key": "x-nso-timestamp",
            "value": "{{VALID_TS_HEADER}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{DIFFERENT_SECRET_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "17. Reject payload tampered after signing + assert no insert",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Sign the ORIGINAL payload with the correct tenant secret, then tamper",
              "// with a field after signing. The signature will no longer match the",
              "// body the server actually receives, so verification must fail.",
              "const original = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman tamper-after-sign rejection test',",
              "    severity: 'low',",
              "    fingerprint: pm.variables.get('TAMPERED_FINGERPRINT'),",
              "    description: 'Original description used to compute signature.',",
              "    remediation: 'Should be rejected before insert.'",
              "  }]",
              "};",
              "const originalBody = JSON.stringify(original);",
              "const secret = pm.variables.get('NSO_HMAC_SECRET');",
              "const sig = CryptoJS.HmacSHA256(originalBody, secret).toString(CryptoJS.enc.Hex);",
              "",
              "// Tamper: mutate a field AFTER computing the signature.",
              "const tampered = JSON.parse(originalBody);",
              "tampered.findings[0].severity = 'critical';",
              "tampered.findings[0].title = 'TAMPERED: escalated severity after signing';",
              "const tamperedBody = JSON.stringify(tampered);",
              "",
              "pm.variables.set('TAMPERED_BODY', tamperedBody);",
              "pm.variables.set('TAMPERED_SIGNATURE', sig);",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');",
              "pm.variables.set('VALID_TS_HEADER', new Date().toISOString());"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook rejects tampered payload with auth error (401/403)', () => {",
              "  pm.expect(pm.response.code).to.be.oneOf([401, 403]);",
              "});",
              "pm.test('response is not ok:true', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* non-JSON error body is fine */ }",
              "});",
              "",
              "// Chained verification: confirm no row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('TAMPERED_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('zero rows inserted for tampered payload', () => pm.expect(rows.length).to.eql(0));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-signature",
            "value": "{{TAMPERED_SIGNATURE}}"
          },
          {
            "key": "x-nso-timestamp",
            "value": "{{VALID_TS_HEADER}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{TAMPERED_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "18. Reject replayed (stale-timestamp) signed payload + assert no insert",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Simulate an attacker replaying a previously captured signed request.",
              "// The body + signature are a valid HMAC pair, but the accompanying",
              "// x-nso-timestamp is 10 minutes old \u2014 beyond the server's 5-minute",
              "// skew window \u2014 so the webhook must reject it before insert.",
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman replay rejection test',",
              "    severity: 'low',",
              "    fingerprint: pm.variables.get('REPLAY_FINGERPRINT'),",
              "    description: 'Captured earlier and replayed after the skew window.',",
              "    remediation: 'Should be rejected as stale.'",
              "  }]",
              "};",
              "const body = JSON.stringify(payload);",
              "const secret = pm.variables.get('NSO_HMAC_SECRET');",
              "const sig = CryptoJS.HmacSHA256(body, secret).toString(CryptoJS.enc.Hex);",
              "const staleTs = new Date(Date.now() - 10 * 60 * 1000).toISOString();",
              "",
              "pm.variables.set('REPLAY_BODY', body);",
              "pm.variables.set('REPLAY_SIGNATURE', sig);",
              "pm.variables.set('REPLAY_TIMESTAMP', staleTs);",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook rejects replayed stale-timestamp request (401/403)', () => {",
              "  pm.expect(pm.response.code).to.be.oneOf([401, 403]);",
              "});",
              "pm.test('response is not ok:true', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* non-JSON error body is fine */ }",
              "});",
              "",
              "// Chained verification: confirm no row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('REPLAY_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('zero rows inserted for replayed request', () => pm.expect(rows.length).to.eql(0));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-signature",
            "value": "{{REPLAY_SIGNATURE}}"
          },
          {
            "key": "x-nso-timestamp",
            "value": "{{REPLAY_TIMESTAMP}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{REPLAY_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "19. Correctly signed payload returns success and inserts a row",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build a fully valid payload and let the collection-level auto-signer",
              "// compute the HMAC-SHA256 signature from the real NSO_HMAC_SECRET.",
              "const fp = pm.variables.get('SUCCESS_FINGERPRINT');",
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman success insert test',",
              "    severity: 'medium',",
              "    fingerprint: fp,",
              "    description: 'Signed with the correct tenant HMAC secret.',",
              "    remediation: 'No action required.'",
              "  }]",
              "};",
              "pm.variables.set('SUCCESS_BODY', JSON.stringify(payload));"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook returns 200 OK', () => pm.response.to.have.status(200));",
              "const body = pm.response.json();",
              "pm.test('ok:true', () => pm.expect(body.ok).to.eql(true));",
              "pm.test('inserted >= 1', () => pm.expect(body.inserted).to.be.at.least(1));",
              "pm.test('total matches findings count', () => pm.expect(body.total).to.eql(1));",
              "",
              "// Chained verification: confirm the row was inserted in Supabase.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('SUCCESS_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('exactly one row inserted', () => pm.expect(rows.length).to.eql(1));",
              "  pm.test('row title matches', () => pm.expect(rows[0].title).to.eql('Postman success insert test'));",
              "  pm.test('row severity matches', () => pm.expect(rows[0].severity).to.eql('medium'));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{SUCCESS_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "20. Omit x-nso-signature header + assert auth error and no insert",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build a valid payload but do not include the x-nso-signature header.",
              "// SKIP_AUTO_SIGN prevents the collection-level signer from adding it.",
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman no-signature rejection test',",
              "    severity: 'low',",
              "    fingerprint: pm.variables.get('NO_SIG_FINGERPRINT'),",
              "    description: 'Sent without the x-nso-signature header entirely.',",
              "    remediation: 'Should be rejected before insert.'",
              "  }]",
              "};",
              "const body = JSON.stringify(payload);",
              "pm.variables.set('NO_SIG_BODY', body);",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');",
              "pm.variables.set('VALID_TS_HEADER', new Date().toISOString());"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook rejects request with no signature header (401/403)', () => {",
              "  pm.expect(pm.response.code).to.be.oneOf([401, 403]);",
              "});",
              "pm.test('response is not ok:true', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* non-JSON body is fine */ }",
              "});",
              "",
              "// Chained verification: confirm no row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('NO_SIG_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('zero rows inserted when signature header is omitted', () => pm.expect(rows.length).to.eql(0));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-timestamp",
            "value": "{{VALID_TS_HEADER}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{NO_SIG_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "21. Reject incorrectly formatted signature + assert no insert",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build a valid payload but send an incorrectly formatted signature header.",
              "// The value contains non-hex characters and is not a valid HMAC-SHA256 hex digest.",
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman incorrectly formatted signature test',",
              "    severity: 'low',",
              "    fingerprint: pm.variables.get('BAD_FORMAT_FINGERPRINT'),",
              "    description: 'Sent with an x-nso-signature value that is not valid hex.',",
              "    remediation: 'Should be rejected before insert.'",
              "  }]",
              "};",
              "const body = JSON.stringify(payload);",
              "pm.variables.set('BAD_FORMAT_BODY', body);",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');",
              "pm.variables.set('VALID_TS_HEADER', new Date().toISOString());"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook rejects incorrectly formatted signature with auth error (401/403)', () => {",
              "  pm.expect(pm.response.code).to.be.oneOf([401, 403]);",
              "});",
              "pm.test('response is not ok:true', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* non-JSON error body is fine */ }",
              "});",
              "",
              "// Chained verification: confirm no row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('BAD_FORMAT_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('zero rows inserted for incorrectly formatted signature', () => pm.expect(rows.length).to.eql(0));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-signature",
            "value": "bad-format-sig!not-valid-hex"
          },
          {
            "key": "x-nso-timestamp",
            "value": "{{VALID_TS_HEADER}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{BAD_FORMAT_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "22. Reject payload signed with wrong algorithm + assert no insert",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build a valid payload but sign it with the wrong algorithm (SHA-1 instead of SHA-256).",
              "// The server expects HMAC-SHA256, so this signature should be rejected even though the secret is correct.",
              "const secret = pm.variables.get('NSO_HMAC_SECRET') || pm.environment.get('NSO_HMAC_SECRET');",
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman wrong algorithm signature test',",
              "    severity: 'low',",
              "    fingerprint: pm.variables.get('WRONG_ALGO_FINGERPRINT'),",
              "    description: 'Signed with HMAC-SHA1 instead of the required HMAC-SHA256.',",
              "    remediation: 'Should be rejected before insert.'",
              "  }]",
              "};",
              "const body = JSON.stringify(payload);",
              "const wrongSignature = CryptoJS.HmacSHA1(body, secret).toString(CryptoJS.enc.Hex);",
              "pm.variables.set('WRONG_ALGO_BODY', body);",
              "pm.variables.set('WRONG_ALGO_SIG', wrongSignature);",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');",
              "pm.variables.set('VALID_TS_HEADER', new Date().toISOString());"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook rejects wrong-algorithm signature with auth error (401/403)', () => {",
              "  pm.expect(pm.response.code).to.be.oneOf([401, 403]);",
              "});",
              "pm.test('response is not ok:true', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* non-JSON error body is fine */ }",
              "});",
              "",
              "// Chained verification: confirm no row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('WRONG_ALGO_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('zero rows inserted for wrong-algorithm signature', () => pm.expect(rows.length).to.eql(0));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-signature",
            "value": "{{WRONG_ALGO_SIG}}"
          },
          {
            "key": "x-nso-timestamp",
            "value": "{{VALID_TS_HEADER}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{WRONG_ALGO_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "23. Reject payload signed with expired timestamp + assert no insert",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build a valid payload, sign it correctly, but send an expired x-nso-timestamp header.",
              "// The timestamp is 10 minutes in the past, beyond the server's 5-minute skew window.",
              "const secret = pm.variables.get('NSO_HMAC_SECRET') || pm.environment.get('NSO_HMAC_SECRET');",
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman expired timestamp signature test',",
              "    severity: 'low',",
              "    fingerprint: pm.variables.get('EXPIRED_TS_FINGERPRINT'),",
              "    description: 'Signed correctly but x-nso-timestamp is 10 minutes old.',",
              "    remediation: 'Should be rejected before insert.'",
              "  }]",
              "};",
              "const body = JSON.stringify(payload);",
              "const signature = CryptoJS.HmacSHA256(body, secret).toString(CryptoJS.enc.Hex);",
              "const expiredTs = new Date(Date.now() - 10 * 60 * 1000).toISOString();",
              "pm.variables.set('EXPIRED_TS_BODY', body);",
              "pm.variables.set('EXPIRED_TS_SIG', signature);",
              "pm.variables.set('EXPIRED_TS_HEADER', expiredTs);",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook rejects expired timestamp with auth error (401/403)', () => {",
              "  pm.expect(pm.response.code).to.be.oneOf([401, 403]);",
              "});",
              "pm.test('response is not ok:true', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* non-JSON body is fine */ }",
              "});",
              "",
              "// Chained verification: confirm no row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('EXPIRED_TS_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('zero rows inserted for expired timestamp signature', () => pm.expect(rows.length).to.eql(0));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-signature",
            "value": "{{EXPIRED_TS_SIG}}"
          },
          {
            "key": "x-nso-timestamp",
            "value": "{{EXPIRED_TS_HEADER}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{EXPIRED_TS_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "24. Reject payload signed with future timestamp + assert no insert",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build a valid payload, sign it correctly, but send a future x-nso-timestamp header.",
              "// The timestamp is 10 minutes in the future, beyond the server's 5-minute skew window.",
              "const secret = pm.variables.get('NSO_HMAC_SECRET') || pm.environment.get('NSO_HMAC_SECRET');",
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman future timestamp signature test',",
              "    severity: 'low',",
              "    fingerprint: pm.variables.get('FUTURE_TS_FINGERPRINT'),",
              "    description: 'Signed correctly but x-nso-timestamp is 10 minutes in the future.',",
              "    remediation: 'Should be rejected before insert.'",
              "  }]",
              "};",
              "const body = JSON.stringify(payload);",
              "const signature = CryptoJS.HmacSHA256(body, secret).toString(CryptoJS.enc.Hex);",
              "const futureTs = new Date(Date.now() + 10 * 60 * 1000).toISOString();",
              "pm.variables.set('FUTURE_TS_BODY', body);",
              "pm.variables.set('FUTURE_TS_SIG', signature);",
              "pm.variables.set('FUTURE_TS_HEADER', futureTs);",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook rejects future timestamp with auth error (401/403)', () => {",
              "  pm.expect(pm.response.code).to.be.oneOf([401, 403]);",
              "});",
              "pm.test('response is not ok:true', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* non-JSON error body is fine */ }",
              "});",
              "",
              "// Chained verification: confirm no row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('FUTURE_TS_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('zero rows inserted for future timestamp signature', () => pm.expect(rows.length).to.eql(0));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-signature",
            "value": "{{FUTURE_TS_SIG}}"
          },
          {
            "key": "x-nso-timestamp",
            "value": "{{FUTURE_TS_HEADER}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{FUTURE_TS_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "25. Reject payload with missing x-nso-timestamp header + assert no insert",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build a valid payload and sign it, but do NOT set x-nso-timestamp.",
              "// The server must reject the request because the timestamp header is required.",
              "const secret = pm.variables.get('NSO_HMAC_SECRET') || pm.environment.get('NSO_HMAC_SECRET');",
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman missing timestamp header test',",
              "    severity: 'low',",
              "    fingerprint: pm.variables.get('OMIT_TS_FINGERPRINT'),",
              "    description: 'Valid HMAC signature, but x-nso-timestamp header is absent.',",
              "    remediation: 'Should be rejected before insert.'",
              "  }]",
              "};",
              "const body = JSON.stringify(payload);",
              "const signature = CryptoJS.HmacSHA256(body, secret).toString(CryptoJS.enc.Hex);",
              "pm.variables.set('OMIT_TS_BODY', body);",
              "pm.variables.set('OMIT_TS_SIG', signature);",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook returns 401 Missing timestamp', () => {",
              "  pm.expect(pm.response.code).to.eql(401);",
              "  pm.expect(pm.response.text()).to.eql('Missing timestamp');",
              "});",
              "pm.test('response is not ok:true', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* non-JSON error body is fine */ }",
              "});",
              "",
              "// Chained verification: confirm no row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('OMIT_TS_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('zero rows inserted for missing timestamp', () => pm.expect(rows.length).to.eql(0));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-signature",
            "value": "{{OMIT_TS_SIG}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{OMIT_TS_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "26. Reject payload with timestamp beyond allowed skew + assert exact stale-timestamp error + no insert",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build a valid payload, sign it correctly, but send an x-nso-timestamp beyond the 5-minute skew window.",
              "// The timestamp is 6 minutes in the past, so the server must return 401 Stale timestamp.",
              "const secret = pm.variables.get('NSO_HMAC_SECRET') || pm.environment.get('NSO_HMAC_SECRET');",
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman beyond-skew timestamp test',",
              "    severity: 'low',",
              "    fingerprint: pm.variables.get('BEYOND_SKEW_FINGERPRINT'),",
              "    description: 'Signed correctly but x-nso-timestamp is 6 minutes old, beyond the 5-minute skew window.',",
              "    remediation: 'Should be rejected before insert.'",
              "  }]",
              "};",
              "const body = JSON.stringify(payload);",
              "const signature = CryptoJS.HmacSHA256(body, secret).toString(CryptoJS.enc.Hex);",
              "const beyondSkewTs = new Date(Date.now() - 6 * 60 * 1000).toISOString();",
              "pm.variables.set('BEYOND_SKEW_BODY', body);",
              "pm.variables.set('BEYOND_SKEW_SIG', signature);",
              "pm.variables.set('BEYOND_SKEW_TS_HEADER', beyondSkewTs);",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook returns 401 Stale timestamp', () => {",
              "  pm.expect(pm.response.code).to.eql(401);",
              "  pm.expect(pm.response.text()).to.eql('Stale timestamp');",
              "});",
              "pm.test('response is not ok:true', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* non-JSON error body is fine */ }",
              "});",
              "",
              "// Chained verification: confirm no row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('BEYOND_SKEW_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('zero rows inserted for beyond-skew timestamp', () => pm.expect(rows.length).to.eql(0));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-signature",
            "value": "{{BEYOND_SKEW_SIG}}"
          },
          {
            "key": "x-nso-timestamp",
            "value": "{{BEYOND_SKEW_TS_HEADER}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{BEYOND_SKEW_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "27. Valid timestamp within skew + valid HMAC returns success and inserts a row",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build a valid payload and sign it with the real tenant secret.",
              "// Explicitly set x-nso-timestamp to a value within the server's 5-minute skew window.",
              "const secret = pm.variables.get('NSO_HMAC_SECRET') || pm.environment.get('NSO_HMAC_SECRET');",
              "const fp = pm.variables.get('VALID_SKEW_FINGERPRINT');",
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman valid skew timestamp success test',",
              "    severity: 'medium',",
              "    fingerprint: fp,",
              "    description: 'Signed correctly with x-nso-timestamp within the 5-minute skew window.',",
              "    remediation: 'No action required.'",
              "  }]",
              "};",
              "const body = JSON.stringify(payload);",
              "const signature = CryptoJS.HmacSHA256(body, secret).toString(CryptoJS.enc.Hex);",
              "const validTs = new Date(Date.now() - 30 * 1000).toISOString();",
              "pm.variables.set('VALID_SKEW_BODY', body);",
              "pm.variables.set('VALID_SKEW_SIG', signature);",
              "pm.variables.set('VALID_SKEW_TS_HEADER', validTs);",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook returns 200 OK', () => pm.response.to.have.status(200));",
              "const body = pm.response.json();",
              "pm.test('ok:true', () => pm.expect(body.ok).to.eql(true));",
              "pm.test('inserted >= 1', () => pm.expect(body.inserted).to.be.at.least(1));",
              "pm.test('total matches findings count', () => pm.expect(body.total).to.eql(1));",
              "",
              "// Chained verification: confirm the row was inserted in Supabase.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('VALID_SKEW_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('exactly one row inserted', () => pm.expect(rows.length).to.eql(1));",
              "  pm.test('row title matches', () => pm.expect(rows[0].title).to.eql('Postman valid skew timestamp success test'));",
              "  pm.test('row severity matches', () => pm.expect(rows[0].severity).to.eql('medium'));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-signature",
            "value": "{{VALID_SKEW_SIG}}"
          },
          {
            "key": "x-nso-timestamp",
            "value": "{{VALID_SKEW_TS_HEADER}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{VALID_SKEW_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "28. Valid timestamp within skew + invalid HMAC returns 401 Invalid signature + no insert",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build a valid payload and timestamp, but sign it with the WRONG secret.",
              "// The timestamp is within the 5-minute skew window, so only the HMAC check should fail.",
              "const secret = pm.variables.get('NSO_HMAC_SECRET') || pm.environment.get('NSO_HMAC_SECRET');",
              "const fp = pm.variables.get('INVALID_SIG_VALID_TS_FINGERPRINT');",
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman valid timestamp invalid HMAC test',",
              "    severity: 'low',",
              "    fingerprint: fp,",
              "    description: 'x-nso-timestamp is within skew, but HMAC signature is invalid.',",
              "    remediation: 'Should be rejected before insert.'",
              "  }]",
              "};",
              "const body = JSON.stringify(payload);",
              "const invalidSig = CryptoJS.HmacSHA256(body, 'this-is-not-the-real-secret').toString(CryptoJS.enc.Hex);",
              "const validTs = new Date(Date.now() - 30 * 1000).toISOString();",
              "pm.variables.set('INVALID_SIG_VALID_TS_BODY', body);",
              "pm.variables.set('INVALID_SIG_VALID_TS_SIG', invalidSig);",
              "pm.variables.set('INVALID_SIG_VALID_TS_HEADER', validTs);",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook returns 401 Invalid signature', () => {",
              "  pm.expect(pm.response.code).to.eql(401);",
              "  pm.expect(pm.response.text()).to.eql('Invalid signature');",
              "});",
              "pm.test('response is not ok:true', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* non-JSON error body is fine */ }",
              "});",
              "",
              "// Chained verification: confirm no row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('INVALID_SIG_VALID_TS_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('zero rows inserted for invalid HMAC with valid timestamp', () => pm.expect(rows.length).to.eql(0));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-signature",
            "value": "{{INVALID_SIG_VALID_TS_SIG}}"
          },
          {
            "key": "x-nso-timestamp",
            "value": "{{INVALID_SIG_VALID_TS_HEADER}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{INVALID_SIG_VALID_TS_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "29. Valid timestamp within skew + missing HMAC signature returns 401 Invalid signature + no insert",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build a valid payload and set a correct x-nso-timestamp within the 5-minute skew window,",
              "// but deliberately omit the x-nso-signature header. The server must reject the request.",
              "const fp = pm.variables.get('MISSING_SIG_VALID_TS_FINGERPRINT');",
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman valid timestamp missing HMAC signature test',",
              "    severity: 'low',",
              "    fingerprint: fp,",
              "    description: 'x-nso-timestamp is within skew, but x-nso-signature header is absent.',",
              "    remediation: 'Should be rejected before insert.'",
              "  }]",
              "};",
              "const body = JSON.stringify(payload);",
              "const validTs = new Date(Date.now() - 30 * 1000).toISOString();",
              "pm.variables.set('MISSING_SIG_VALID_TS_BODY', body);",
              "pm.variables.set('MISSING_SIG_VALID_TS_HEADER', validTs);",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook returns 401 Invalid signature', () => {",
              "  pm.expect(pm.response.code).to.eql(401);",
              "  pm.expect(pm.response.text()).to.eql('Invalid signature');",
              "});",
              "pm.test('response is not ok:true', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* non-JSON error body is fine */ }",
              "});",
              "",
              "// Chained verification: confirm no row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('MISSING_SIG_VALID_TS_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('zero rows inserted for missing HMAC with valid timestamp', () => pm.expect(rows.length).to.eql(0));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-timestamp",
            "value": "{{MISSING_SIG_VALID_TS_HEADER}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{MISSING_SIG_VALID_TS_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "30. Reject timestamp older than 5 minutes + assert exact stale-timestamp error + no insert",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build a valid payload, sign it correctly, but send an x-nso-timestamp older than the 5-minute skew window.",
              "// The timestamp is 7 minutes in the past, so the server must return 401 Stale timestamp.",
              "const secret = pm.variables.get('NSO_HMAC_SECRET') || pm.environment.get('NSO_HMAC_SECRET');",
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman older-than-5-minutes timestamp test',",
              "    severity: 'low',",
              "    fingerprint: pm.variables.get('OLDER_THAN_5MIN_FINGERPRINT'),",
              "    description: 'Signed correctly but x-nso-timestamp is 7 minutes old, older than the 5-minute skew window.',",
              "    remediation: 'Should be rejected before insert.'",
              "  }]",
              "};",
              "const body = JSON.stringify(payload);",
              "const signature = CryptoJS.HmacSHA256(body, secret).toString(CryptoJS.enc.Hex);",
              "const oldTs = new Date(Date.now() - 7 * 60 * 1000).toISOString();",
              "pm.variables.set('OLDER_THAN_5MIN_BODY', body);",
              "pm.variables.set('OLDER_THAN_5MIN_SIG', signature);",
              "pm.variables.set('OLDER_THAN_5MIN_TS_HEADER', oldTs);",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook returns 401 Stale timestamp', () => {",
              "  pm.expect(pm.response.code).to.eql(401);",
              "  pm.expect(pm.response.text()).to.eql('Stale timestamp');",
              "});",
              "pm.test('response is not ok:true', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* non-JSON error body is fine */ }",
              "});",
              "",
              "// Chained verification: confirm no row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('OLDER_THAN_5MIN_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('zero rows inserted for timestamp older than 5 minutes', () => pm.expect(rows.length).to.eql(0));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-signature",
            "value": "{{OLDER_THAN_5MIN_SIG}}"
          },
          {
            "key": "x-nso-timestamp",
            "value": "{{OLDER_THAN_5MIN_TS_HEADER}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{OLDER_THAN_5MIN_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
          "{{NSO_TENANT_SLUG}}"
        ]
      }
      }
    },
    {
      "name": "31. Current x-nso-timestamp + correct HMAC returns 200 success and inserts a row",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build a valid payload and sign it with the real tenant secret.",
              "// Use the current time as x-nso-timestamp so it is well within the 5-minute skew window.",
              "const secret = pm.variables.get('NSO_HMAC_SECRET') || pm.environment.get('NSO_HMAC_SECRET');",
              "const fp = pm.variables.get('CURRENT_TS_SUCCESS_FINGERPRINT');",
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman current timestamp success test',",
              "    severity: 'low',",
              "    fingerprint: fp,",
              "    description: 'Signed correctly with the current x-nso-timestamp.',",
              "    remediation: 'No action required.'",
              "  }]",
              "};",
              "const body = JSON.stringify(payload);",
              "const signature = CryptoJS.HmacSHA256(body, secret).toString(CryptoJS.enc.Hex);",
              "const currentTs = new Date().toISOString();",
              "pm.variables.set('CURRENT_TS_SUCCESS_BODY', body);",
              "pm.variables.set('CURRENT_TS_SUCCESS_SIG', signature);",
              "pm.variables.set('CURRENT_TS_SUCCESS_TS_HEADER', currentTs);",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook returns 200 OK', () => pm.response.to.have.status(200));",
              "const body = pm.response.json();",
              "pm.test('exact success body', () => {",
              "  pm.expect(body).to.eql({ ok: true, inserted: 1, updated: 0, total: 1 });",
              "});",
              "",
              "// Chained verification: confirm the row was inserted in Supabase.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('CURRENT_TS_SUCCESS_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('exactly one row inserted', () => pm.expect(rows.length).to.eql(1));",
              "  pm.test('row title matches', () => pm.expect(rows[0].title).to.eql('Postman current timestamp success test'));",
              "  pm.test('row severity matches', () => pm.expect(rows[0].severity).to.eql('low'));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-signature",
            "value": "{{CURRENT_TS_SUCCESS_SIG}}"
          },
          {
            "key": "x-nso-timestamp",
            "value": "{{CURRENT_TS_SUCCESS_TS_HEADER}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{CURRENT_TS_SUCCESS_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "32. Current x-nso-timestamp + incorrect x-nso-signature returns 401 Invalid signature and no insert",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build a valid payload and set x-nso-timestamp to the current time,",
              "// but sign it with the WRONG secret so the server-side HMAC check fails.",
              "const fp = pm.variables.get('CURRENT_INVALID_SIG_FINGERPRINT');",
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman current timestamp incorrect signature test',",
              "    severity: 'low',",
              "    fingerprint: fp,",
              "    description: 'x-nso-timestamp is current, but HMAC signature is incorrect.',",
              "    remediation: 'Should be rejected before insert.'",
              "  }]",
              "};",
              "const body = JSON.stringify(payload);",
              "const invalidSig = CryptoJS.HmacSHA256(body, 'this-is-not-the-real-secret').toString(CryptoJS.enc.Hex);",
              "const currentTs = new Date().toISOString();",
              "pm.variables.set('CURRENT_INVALID_SIG_BODY', body);",
              "pm.variables.set('CURRENT_INVALID_SIG_SIG', invalidSig);",
              "pm.variables.set('CURRENT_INVALID_SIG_TS_HEADER', currentTs);",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook returns 401 Invalid signature', () => {",
              "  pm.expect(pm.response.code).to.eql(401);",
              "  pm.expect(pm.response.text()).to.eql('Invalid signature');",
              "});",
              "pm.test('response is not ok:true', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* non-JSON error body is fine */ }",
              "});",
              "",
              "// Chained verification: confirm no row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('CURRENT_INVALID_SIG_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('zero rows inserted for incorrect signature with current timestamp', () => pm.expect(rows.length).to.eql(0));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-signature",
            "value": "{{CURRENT_INVALID_SIG_SIG}}"
          },
          {
            "key": "x-nso-timestamp",
            "value": "{{CURRENT_INVALID_SIG_TS_HEADER}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{CURRENT_INVALID_SIG_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "33. Omit x-nso-signature with current x-nso-timestamp returns 401 Invalid signature and no insert",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build a valid payload and set x-nso-timestamp to the current time,",
              "// but intentionally omit the x-nso-signature header.",
              "const fp = pm.variables.get('OMIT_SIG_VALID_TS_FINGERPRINT');",
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman omit signature with current timestamp test',",
              "    severity: 'low',",
              "    fingerprint: fp,",
              "    description: 'x-nso-timestamp is current, but x-nso-signature header is missing.',",
              "    remediation: 'Should be rejected before insert.'",
              "  }]",
              "};",
              "const body = JSON.stringify(payload);",
              "const currentTs = new Date().toISOString();",
              "pm.variables.set('OMIT_SIG_VALID_TS_BODY', body);",
              "pm.variables.set('OMIT_SIG_VALID_TS_HEADER', currentTs);",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook returns 401 Invalid signature', () => {",
              "  pm.expect(pm.response.code).to.eql(401);",
              "  pm.expect(pm.response.text()).to.eql('Invalid signature');",
              "});",
              "pm.test('response is not ok:true', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* non-JSON error body is fine */ }",
              "});",
              "",
              "// Chained verification: confirm no row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('OMIT_SIG_VALID_TS_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('zero rows inserted when signature is omitted', () => pm.expect(rows.length).to.eql(0));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-timestamp",
            "value": "{{OMIT_SIG_VALID_TS_HEADER}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{OMIT_SIG_VALID_TS_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "34. Omit x-nso-timestamp with valid HMAC signature returns 401 Missing timestamp and no insert",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build a valid payload and sign it with the real tenant secret,",
              "// but deliberately omit the x-nso-timestamp header. The server must reject the request.",
              "const secret = pm.variables.get('NSO_HMAC_SECRET') || pm.environment.get('NSO_HMAC_SECRET');",
              "const fp = pm.variables.get('OMIT_TS_VALID_SIG_FINGERPRINT');",
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman omit timestamp with valid signature test',",
              "    severity: 'low',",
              "    fingerprint: fp,",
              "    description: 'HMAC signature is valid, but x-nso-timestamp header is absent.',",
              "    remediation: 'Should be rejected before insert.'",
              "  }]",
              "};",
              "const body = JSON.stringify(payload);",
              "const signature = CryptoJS.HmacSHA256(body, secret).toString(CryptoJS.enc.Hex);",
              "pm.variables.set('OMIT_TS_VALID_SIG_BODY', body);",
              "pm.variables.set('OMIT_TS_VALID_SIG_SIG', signature);",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook returns 401 Missing timestamp', () => {",
              "  pm.expect(pm.response.code).to.eql(401);",
              "  pm.expect(pm.response.text()).to.eql('Missing timestamp');",
              "});",
              "pm.test('response is not ok:true', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* non-JSON error body is fine */ }",
              "});",
              "",
              "// Chained verification: confirm no row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('OMIT_TS_VALID_SIG_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('zero rows inserted when timestamp is omitted', () => pm.expect(rows.length).to.eql(0));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-signature",
            "value": "{{OMIT_TS_VALID_SIG_SIG}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{OMIT_TS_VALID_SIG_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "35. Invalid x-nso-timestamp format returns 401 Invalid timestamp and no insert",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build a valid payload and sign it with the real tenant secret,",
              "// but send an x-nso-timestamp that is not parseable as an ISO 8601 date.",
              "const secret = pm.variables.get('NSO_HMAC_SECRET') || pm.environment.get('NSO_HMAC_SECRET');",
              "const fp = pm.variables.get('INVALID_TS_FORMAT_FINGERPRINT');",
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman invalid timestamp format test',",
              "    severity: 'low',",
              "    fingerprint: fp,",
              "    description: 'x-nso-timestamp is present but not a valid date format.',",
              "    remediation: 'Should be rejected before insert.'",
              "  }]",
              "};",
              "const body = JSON.stringify(payload);",
              "const signature = CryptoJS.HmacSHA256(body, secret).toString(CryptoJS.enc.Hex);",
              "pm.variables.set('INVALID_TS_FORMAT_BODY', body);",
              "pm.variables.set('INVALID_TS_FORMAT_SIG', signature);",
              "pm.variables.set('INVALID_TS_FORMAT_HEADER', 'this-is-not-a-valid-timestamp');",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook returns 401 Invalid timestamp', () => {",
              "  pm.expect(pm.response.code).to.eql(401);",
              "  pm.expect(pm.response.text()).to.eql('Invalid timestamp');",
              "});",
              "pm.test('response is not ok:true', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* non-JSON error body is fine */ }",
              "});",
              "",
              "// Chained verification: confirm no row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('INVALID_TS_FORMAT_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('zero rows inserted for invalid timestamp format', () => pm.expect(rows.length).to.eql(0));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-signature",
            "value": "{{INVALID_TS_FORMAT_SIG}}"
          },
          {
            "key": "x-nso-timestamp",
            "value": "{{INVALID_TS_FORMAT_HEADER}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{INVALID_TS_FORMAT_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "36. Sign with incorrect tenant secret returns 401 Invalid signature and no insert",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build a valid payload and sign it with an INCORRECT tenant secret.",
              "// The signature is a well-formed HMAC, but it does not match the secret",
              "// configured for this tenant, so the server must reject it.",
              "const fp = pm.variables.get('INCORRECT_SECRET_FINGERPRINT');",
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman incorrect tenant secret test',",
              "    severity: 'low',",
              "    fingerprint: fp,",
              "    description: 'Signed with a secret that is not the tenant HMAC secret.',",
              "    remediation: 'Should be rejected before insert.'",
              "  }]",
              "};",
              "const body = JSON.stringify(payload);",
              "const wrongSecret = 'this-is-not-the-tenant-secret';",
              "const signature = CryptoJS.HmacSHA256(body, wrongSecret).toString(CryptoJS.enc.Hex);",
              "const currentTs = new Date().toISOString();",
              "pm.variables.set('INCORRECT_SECRET_BODY', body);",
              "pm.variables.set('INCORRECT_SECRET_SIG', signature);",
              "pm.variables.set('INCORRECT_SECRET_TS_HEADER', currentTs);",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook returns 401 Invalid signature', () => {",
              "  pm.expect(pm.response.code).to.eql(401);",
              "  pm.expect(pm.response.text()).to.eql('Invalid signature');",
              "});",
              "pm.test('response is not ok:true', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* non-JSON error body is fine */ }",
              "});",
              "",
              "// Chained verification: confirm no row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('INCORRECT_SECRET_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('zero rows inserted for incorrect tenant secret', () => pm.expect(rows.length).to.eql(0));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-signature",
            "value": "{{INCORRECT_SECRET_SIG}}"
          },
          {
            "key": "x-nso-timestamp",
            "value": "{{INCORRECT_SECRET_TS_HEADER}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{INCORRECT_SECRET_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "37. Sign request then modify body returns 401 Invalid signature and no insert",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build a valid payload and sign it with the real tenant secret,",
              "// then mutate the body before it is sent. The signature no longer matches",
              "// the bytes on the wire, so the server must reject the request.",
              "const secret = pm.variables.get('NSO_HMAC_SECRET') || pm.environment.get('NSO_HMAC_SECRET');",
              "const fp = pm.variables.get('MODIFIED_BODY_FINGERPRINT');",
              "const originalPayload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman signed-then-modified body test',",
              "    severity: 'low',",
              "    fingerprint: fp,",
              "    description: 'Signed correctly, then body was altered before sending.',",
              "    remediation: 'Should be rejected before insert.'",
              "  }]",
              "};",
              "const originalBody = JSON.stringify(originalPayload);",
              "const signature = CryptoJS.HmacSHA256(originalBody, secret).toString(CryptoJS.enc.Hex);",
              "const modifiedPayload = JSON.parse(originalBody);",
              "modifiedPayload.findings[0].severity = 'critical';",
              "const modifiedBody = JSON.stringify(modifiedPayload);",
              "const currentTs = new Date().toISOString();",
              "pm.variables.set('MODIFIED_BODY_ORIGINAL_SIG', signature);",
              "pm.variables.set('MODIFIED_BODY', modifiedBody);",
              "pm.variables.set('MODIFIED_BODY_TS_HEADER', currentTs);",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook returns 401 Invalid signature', () => {",
              "  pm.expect(pm.response.code).to.eql(401);",
              "  pm.expect(pm.response.text()).to.eql('Invalid signature');",
              "});",
              "pm.test('response is not ok:true', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* non-JSON error body is fine */ }",
              "});",
              "",
              "// Chained verification: confirm no row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('MODIFIED_BODY_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('zero rows inserted when body is modified after signing', () => pm.expect(rows.length).to.eql(0));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-signature",
            "value": "{{MODIFIED_BODY_ORIGINAL_SIG}}"
          },
          {
            "key": "x-nso-timestamp",
            "value": "{{MODIFIED_BODY_TS_HEADER}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{MODIFIED_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
        "name": "38. Replay identical signature and timestamp returns 409 Replay detected and only one insert",
        "event": [
          {
            "listen": "prerequest",
            "script": {
              "type": "text/javascript",
              "exec": [
                "// Clean up any previous rows for this fingerprint so the count assertion is deterministic.",
                "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
                "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
                "const fp = pm.variables.get('REPLAY_NONCE_FINGERPRINT');",
                "pm.sendRequest({",
                "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
                "  method: 'DELETE',",
                "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}`, prefer: 'return=minimal' }",
                "}, () => { /* ignore cleanup errors */ });",
                "",
                "// Build a valid payload and sign it with the real tenant secret.",
                "const secret = pm.variables.get('NSO_HMAC_SECRET') || pm.environment.get('NSO_HMAC_SECRET');",
                "const payload = {",
                "  findings: [{",
                "    scanner: 'postman-smoke',",
                "    asset: 'example.com',",
                "    title: 'Postman nonce replay test',",
                "    severity: 'low',",
                "    fingerprint: fp,",
                "    description: 'First valid request; identical request should be rejected as replay.',",
                "    remediation: 'Should only insert once.'",
                "  }]",
                "};",
                "const body = JSON.stringify(payload);",
                "const signature = CryptoJS.HmacSHA256(body, secret).toString(CryptoJS.enc.Hex);",
                "const currentTs = new Date().toISOString();",
                "pm.variables.set('REPLAY_NONCE_BODY', body);",
                "pm.variables.set('REPLAY_NONCE_SIG', signature);",
                "pm.variables.set('REPLAY_NONCE_TS_HEADER', currentTs);",
                "pm.variables.set('SKIP_AUTO_SIGN', 'true');"
              ]
            }
          },
          {
            "listen": "test",
            "script": {
              "type": "text/javascript",
              "exec": [
                "pm.test('first webhook request returns 200 ok:true', () => {",
                "  pm.response.to.have.status(200);",
                "  pm.expect(pm.response.json().ok).to.eql(true);",
                "});",
                "",
                "// Replay the exact same request: same body, same signature, same timestamp.",
                "const host = pm.variables.get('NSO_WEBHOOK_HOST');",
                "const slug = pm.variables.get('NSO_TENANT_SLUG');",
                "const body = pm.variables.get('REPLAY_NONCE_BODY');",
                "const signature = pm.variables.get('REPLAY_NONCE_SIG');",
                "const ts = pm.variables.get('REPLAY_NONCE_TS_HEADER');",
                "",
                "pm.sendRequest({",
                "  url: `${host}/api/public/ingest/${slug}`,",
                "  method: 'POST',",
                "  header: {",
                "    'content-type': 'application/json',",
                "    'x-nso-signature': signature,",
                "    'x-nso-timestamp': ts",
                "  },",
                "  body: { mode: 'raw', raw: body }",
                "}, (err, replayRes) => {",
                "  pm.test('replay returns 409 Replay detected', () => {",
                "    pm.expect(err).to.be.null;",
                "    pm.expect(replayRes.code).to.eql(409);",
                "    pm.expect(replayRes.text()).to.eql('Replay detected');",
                "  });",
                "",
                "  // Verify exactly one row was inserted (the first request, not the replay).",
                "  const supabaseUrl = pm.variables.get('SUPABASE_URL');",
                "  const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
                "  const fp = pm.variables.get('REPLAY_NONCE_FINGERPRINT');",
                "  pm.sendRequest({",
                "    url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
                "    method: 'GET',",
                "    header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
                "  }, (err2, res2) => {",
                "    pm.test('supabase lookup 200', () => {",
                "      pm.expect(err2).to.be.null;",
                "      pm.expect(res2.code).to.eql(200);",
                "    });",
                "    const rows = res2.json();",
                "    pm.test('exactly one row inserted after replay is rejected', () => pm.expect(rows.length).to.eql(1));",
                "  });",
                "});"
              ]
            }
          }
        ],
        "request": {
          "method": "POST",
          "header": [
            {
              "key": "content-type",
              "value": "application/json"
            },
            {
              "key": "x-nso-signature",
              "value": "{{REPLAY_NONCE_SIG}}"
            },
            {
              "key": "x-nso-timestamp",
              "value": "{{REPLAY_NONCE_TS_HEADER}}"
            }
          ],
          "body": {
            "mode": "raw",
            "raw": "{{REPLAY_NONCE_BODY}}",
            "options": {
              "raw": {
                "language": "json"
              }
            }
          },
          "url": {
            "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
            "host": [
              "{{NSO_WEBHOOK_HOST}}"
            ],
            "path": [
              "api",
              "public",
              "ingest",
              "{{NSO_TENANT_SLUG}}"
            ]
          }
        }
    },
    {
      "name": "39. Omit x-nso-signature header returns 401 Invalid signature and no insert",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build a valid payload and set x-nso-timestamp, but intentionally omit",
              "// the x-nso-signature header. The server must reject it as an invalid signature.",
              "const fp = pm.variables.get('OMIT_SIG_EXACT_FINGERPRINT');",
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman omit signature exact error test',",
              "    severity: 'low',",
              "    fingerprint: fp,",
              "    description: 'x-nso-signature header is intentionally absent.',",
              "    remediation: 'Should be rejected before insert.'",
              "  }]",
              "};",
              "const body = JSON.stringify(payload);",
              "const currentTs = new Date().toISOString();",
              "pm.variables.set('OMIT_SIG_EXACT_BODY', body);",
              "pm.variables.set('OMIT_SIG_EXACT_TS_HEADER', currentTs);",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook returns 401 Invalid signature', () => {",
              "  pm.expect(pm.response.code).to.eql(401);",
              "  pm.expect(pm.response.text()).to.eql('Invalid signature');",
              "});",
              "pm.test('response is not ok:true', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* non-JSON error body is fine */ }",
              "});",
              "",
              "// Chained verification: confirm no row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('OMIT_SIG_EXACT_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('zero rows inserted when signature is omitted', () => pm.expect(rows.length).to.eql(0));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-timestamp",
            "value": "{{OMIT_SIG_EXACT_TS_HEADER}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{OMIT_SIG_EXACT_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "40. Omit x-nso-timestamp header returns 401 Missing timestamp and no insert",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build a valid payload and sign it with the real tenant secret, but intentionally omit",
              "// the x-nso-timestamp header. The server must reject it as a missing timestamp.",
              "const secret = pm.variables.get('NSO_HMAC_SECRET') || pm.environment.get('NSO_HMAC_SECRET');",
              "const fp = pm.variables.get('OMIT_TS_EXACT_FINGERPRINT');",
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman omit timestamp exact error test',",
              "    severity: 'low',",
              "    fingerprint: fp,",
              "    description: 'x-nso-timestamp header is intentionally absent.',",
              "    remediation: 'Should be rejected before insert.'",
              "  }]",
              "};",
              "const body = JSON.stringify(payload);",
              "const signature = CryptoJS.HmacSHA256(body, secret).toString(CryptoJS.enc.Hex);",
              "pm.variables.set('OMIT_TS_EXACT_BODY', body);",
              "pm.variables.set('OMIT_TS_EXACT_SIG', signature);",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook returns 401 Missing timestamp', () => {",
              "  pm.expect(pm.response.code).to.eql(401);",
              "  pm.expect(pm.response.text()).to.eql('Missing timestamp');",
              "});",
              "pm.test('response is not ok:true', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* non-JSON error body is fine */ }",
              "});",
              "",
              "// Chained verification: confirm no row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('OMIT_TS_EXACT_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('zero rows inserted when timestamp is omitted', () => pm.expect(rows.length).to.eql(0));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-signature",
            "value": "{{OMIT_TS_EXACT_SIG}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{OMIT_TS_EXACT_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "41. Wrong signature with valid body and timestamp returns 401 Invalid signature and no insert",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build a valid payload, sign it with the real tenant secret, and keep the timestamp valid,",
              "// then intentionally corrupt the signature so the body and timestamp are correct but the",
              "// HMAC value does not match. The server must reject it as an invalid signature.",
              "const secret = pm.variables.get('NSO_HMAC_SECRET') || pm.environment.get('NSO_HMAC_SECRET');",
              "const fp = pm.variables.get('WRONG_SIG_VALID_BODY_TS_FINGERPRINT');",
              "const payload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Postman wrong signature valid body and timestamp test',",
              "    severity: 'low',",
              "    fingerprint: fp,",
              "    description: 'Body and timestamp are valid; x-nso-signature is intentionally wrong.',",
              "    remediation: 'Should be rejected before insert.'",
              "  }]",
              "};",
              "const body = JSON.stringify(payload);",
              "const validSig = CryptoJS.HmacSHA256(body, secret).toString(CryptoJS.enc.Hex);",
              "// Corrupt the signature by reversing the hex string so it is the wrong value",
              "// for the same correct body and timestamp.",
              "const wrongSig = validSig.split('').reverse().join('');",
              "const currentTs = new Date().toISOString();",
              "pm.variables.set('WRONG_SIG_VALID_BODY_TS_BODY', body);",
              "pm.variables.set('WRONG_SIG_VALID_BODY_TS_SIG', wrongSig);",
              "pm.variables.set('WRONG_SIG_VALID_BODY_TS_HEADER', currentTs);",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook returns 401 Invalid signature', () => {",
              "  pm.expect(pm.response.code).to.eql(401);",
              "  pm.expect(pm.response.text()).to.eql('Invalid signature');",
              "});",
              "pm.test('response is not ok:true', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* non-JSON error body is fine */ }",
              "});",
              "",
              "// Chained verification: confirm no row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('WRONG_SIG_VALID_BODY_TS_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('zero rows inserted when signature is wrong', () => pm.expect(rows.length).to.eql(0));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-signature",
            "value": "{{WRONG_SIG_VALID_BODY_TS_SIG}}"
          },
          {
            "key": "x-nso-timestamp",
            "value": "{{WRONG_SIG_VALID_BODY_TS_HEADER}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{WRONG_SIG_VALID_BODY_TS_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "42. Correct signature and timestamp with invalid payload body returns 400 Invalid payload and no insert",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build an INVALID payload (missing required 'title' field), then sign it correctly",
              "// with the real tenant secret and send it with a valid timestamp. The signature and",
              "// timestamp headers are correct for the body on the wire, but the body fails schema",
              "// validation, so the server must reject it as an invalid payload.",
              "const secret = pm.variables.get('NSO_HMAC_SECRET') || pm.environment.get('NSO_HMAC_SECRET');",
              "const fp = pm.variables.get('VALID_SIG_TS_MODIFIED_BODY_FINGERPRINT');",
              "const invalidPayload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    // title is intentionally omitted to violate the findings schema",
              "    severity: 'low',",
              "    fingerprint: fp,",
              "    description: 'Valid signature over an invalid payload body.',",
              "    remediation: 'Should be rejected by schema validation before insert.'",
              "  }]",
              "};",
              "const body = JSON.stringify(invalidPayload);",
              "const signature = CryptoJS.HmacSHA256(body, secret).toString(CryptoJS.enc.Hex);",
              "const currentTs = new Date().toISOString();",
              "pm.variables.set('VALID_SIG_TS_MODIFIED_BODY', body);",
              "pm.variables.set('VALID_SIG_TS_MODIFIED_BODY_SIG', signature);",
              "pm.variables.set('VALID_SIG_TS_MODIFIED_BODY_TS_HEADER', currentTs);",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook returns 400 Invalid payload', () => {",
              "  pm.expect(pm.response.code).to.eql(400);",
              "  const json = pm.response.json();",
              "  pm.expect(json.error).to.eql('Invalid payload');",
              "});",
              "pm.test('response is not ok:true', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* expected error body */ }",
              "});",
              "",
              "// Chained verification: confirm no row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('VALID_SIG_TS_MODIFIED_BODY_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('zero rows inserted for invalid payload body', () => pm.expect(rows.length).to.eql(0));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-signature",
            "value": "{{VALID_SIG_TS_MODIFIED_BODY_SIG}}"
          },
          {
            "key": "x-nso-timestamp",
            "value": "{{VALID_SIG_TS_MODIFIED_BODY_TS_HEADER}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{VALID_SIG_TS_MODIFIED_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "43. Correct body with valid signature and timestamp returns success and inserts a row",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build a fully valid payload, sign it with the real tenant secret, and send it with",
              "// a current timestamp. This is the canonical happy-path test: every header and byte",
              "// is correct, so the server must accept the ingest and persist exactly one row.",
              "const secret = pm.variables.get('NSO_HMAC_SECRET') || pm.environment.get('NSO_HMAC_SECRET');",
              "const fp = pm.variables.get('VALID_FULL_SUCCESS_FINGERPRINT');",
              "const validPayload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Valid full-success ingest from Postman step 43',",
              "    severity: 'medium',",
              "    fingerprint: fp,",
              "    description: 'A correctly signed, schema-valid payload used for the end-to-end success test.',",
              "    remediation: 'No action required — this is a test finding.'",
              "  }]",
              "};",
              "const body = JSON.stringify(validPayload);",
              "const signature = CryptoJS.HmacSHA256(body, secret).toString(CryptoJS.enc.Hex);",
              "const currentTs = new Date().toISOString();",
              "pm.variables.set('VALID_FULL_SUCCESS_BODY', body);",
              "pm.variables.set('VALID_FULL_SUCCESS_SIG', signature);",
              "pm.variables.set('VALID_FULL_SUCCESS_TS_HEADER', currentTs);",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook returns 200 ok:true with insert metrics', () => {",
              "  pm.expect(pm.response.code).to.eql(200);",
              "  const json = pm.response.json();",
              "  pm.expect(json.ok).to.eql(true);",
              "  pm.expect(json.inserted).to.be.at.least(1);",
              "  pm.expect(json.total).to.eql(1);",
              "});",
              "",
              "// Chained verification: confirm exactly one row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('VALID_FULL_SUCCESS_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('exactly one row inserted for valid full-success request', () => {",
              "    pm.expect(rows.length).to.eql(1);",
              "    pm.expect(rows[0].title).to.eql('Valid full-success ingest from Postman step 43');",
              "    pm.expect(rows[0].severity).to.eql('medium');",
              "  });",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-signature",
            "value": "{{VALID_FULL_SUCCESS_SIG}}"
          },
          {
            "key": "x-nso-timestamp",
            "value": "{{VALID_FULL_SUCCESS_TS_HEADER}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{VALID_FULL_SUCCESS_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    },
    {
      "name": "44. Valid body with correct signature but expired timestamp returns 401 Stale timestamp and no insert",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Build a fully valid payload, sign it correctly with the real tenant secret,",
              "// but send an x-nso-timestamp that is well beyond the server's 5-minute skew window.",
              "// The signature is correct for the body, yet the expired timestamp must be rejected.",
              "const secret = pm.variables.get('NSO_HMAC_SECRET') || pm.environment.get('NSO_HMAC_SECRET');",
              "const fp = pm.variables.get('EXPIRED_TS_EXACT_FINGERPRINT');",
              "const validPayload = {",
              "  findings: [{",
              "    scanner: 'postman-smoke',",
              "    asset: 'example.com',",
              "    title: 'Valid body with expired timestamp from Postman step 44',",
              "    severity: 'low',",
              "    fingerprint: fp,",
              "    description: 'A correctly signed payload with an expired timestamp.',",
              "    remediation: 'Should be rejected before insert.'",
              "  }]",
              "};",
              "const body = JSON.stringify(validPayload);",
              "const signature = CryptoJS.HmacSHA256(body, secret).toString(CryptoJS.enc.Hex);",
              "const expiredTs = new Date(Date.now() - 10 * 60 * 1000).toISOString();",
              "pm.variables.set('EXPIRED_TS_EXACT_BODY', body);",
              "pm.variables.set('EXPIRED_TS_EXACT_SIG', signature);",
              "pm.variables.set('EXPIRED_TS_EXACT_TS_HEADER', expiredTs);",
              "pm.variables.set('SKIP_AUTO_SIGN', 'true');"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('webhook returns 401 Stale timestamp', () => {",
              "  pm.expect(pm.response.code).to.eql(401);",
              "  pm.expect(pm.response.text()).to.eql('Stale timestamp');",
              "});",
              "pm.test('response is not ok:true', () => {",
              "  try { pm.expect(pm.response.json().ok).to.not.eql(true); } catch (e) { /* expected error body */ }",
              "});",
              "",
              "// Chained verification: confirm no row was inserted for this fingerprint.",
              "const supabaseUrl = pm.variables.get('SUPABASE_URL');",
              "const serviceKey = pm.variables.get('SUPABASE_SERVICE_ROLE_KEY');",
              "const fp = pm.variables.get('EXPIRED_TS_EXACT_FINGERPRINT');",
              "pm.sendRequest({",
              "  url: `${supabaseUrl}/rest/v1/findings?fingerprint=eq.${encodeURIComponent(fp)}`,",
              "  method: 'GET',",
              "  header: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }",
              "}, (err, res) => {",
              "  pm.test('supabase lookup 200', () => {",
              "    pm.expect(err).to.be.null;",
              "    pm.expect(res.code).to.eql(200);",
              "  });",
              "  const rows = res.json();",
              "  pm.test('zero rows inserted for expired timestamp request', () => pm.expect(rows.length).to.eql(0));",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          },
          {
            "key": "x-nso-signature",
            "value": "{{EXPIRED_TS_EXACT_SIG}}"
          },
          {
            "key": "x-nso-timestamp",
            "value": "{{EXPIRED_TS_EXACT_TS_HEADER}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{{EXPIRED_TS_EXACT_BODY}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{NSO_WEBHOOK_HOST}}/api/public/ingest/{{NSO_TENANT_SLUG}}",
          "host": [
            "{{NSO_WEBHOOK_HOST}}"
          ],
          "path": [
            "api",
            "public",
            "ingest",
            "{{NSO_TENANT_SLUG}}"
          ]
        }
      }
    }
    ]
  }
