|
| 1 | +ALTER TABLE "webhooks" |
| 2 | + ADD COLUMN IF NOT EXISTS "signature_version" TEXT NOT NULL DEFAULT 'v1', |
| 3 | + ADD COLUMN IF NOT EXISTS "secret_expires_at" TIMESTAMP(3), |
| 4 | + ADD COLUMN IF NOT EXISTS "rotated_at" TIMESTAMP(3), |
| 5 | + ADD COLUMN IF NOT EXISTS "encryption_public_key" TEXT; |
| 6 | + |
| 7 | +ALTER TABLE "audit_logs" |
| 8 | + ADD COLUMN IF NOT EXISTS "timestamp" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, |
| 9 | + ADD COLUMN IF NOT EXISTS "actor" TEXT NOT NULL DEFAULT 'system', |
| 10 | + ADD COLUMN IF NOT EXISTS "resource" TEXT NOT NULL DEFAULT 'legacy', |
| 11 | + ADD COLUMN IF NOT EXISTS "details" JSONB, |
| 12 | + ADD COLUMN IF NOT EXISTS "previous_hash" TEXT NOT NULL DEFAULT repeat('0', 64), |
| 13 | + ADD COLUMN IF NOT EXISTS "hash" TEXT, |
| 14 | + ADD COLUMN IF NOT EXISTS "anchor_id" TEXT, |
| 15 | + ADD COLUMN IF NOT EXISTS "archived_at" TIMESTAMP(3), |
| 16 | + ADD COLUMN IF NOT EXISTS "cold_archived_at" TIMESTAMP(3); |
| 17 | + |
| 18 | +UPDATE "audit_logs" |
| 19 | +SET "hash" = md5("id" || "created_at"::text || "action") |
| 20 | +WHERE "hash" IS NULL; |
| 21 | + |
| 22 | +ALTER TABLE "audit_logs" ALTER COLUMN "hash" SET NOT NULL; |
| 23 | + |
| 24 | +CREATE UNIQUE INDEX IF NOT EXISTS "audit_logs_hash_key" ON "audit_logs"("hash"); |
| 25 | +CREATE INDEX IF NOT EXISTS "audit_logs_timestamp_idx" ON "audit_logs"("timestamp"); |
| 26 | +CREATE INDEX IF NOT EXISTS "audit_logs_actor_idx" ON "audit_logs"("actor"); |
| 27 | +CREATE INDEX IF NOT EXISTS "audit_logs_action_idx" ON "audit_logs"("action"); |
| 28 | +CREATE INDEX IF NOT EXISTS "audit_logs_actor_action_timestamp_idx" ON "audit_logs"("actor", "action", "timestamp"); |
| 29 | + |
| 30 | +CREATE TABLE IF NOT EXISTS "audit_anchors" ( |
| 31 | + "id" TEXT NOT NULL, |
| 32 | + "latest_hash" TEXT NOT NULL, |
| 33 | + "chain" TEXT NOT NULL, |
| 34 | + "transaction_hash" TEXT, |
| 35 | + "block_number" TEXT, |
| 36 | + "status" TEXT NOT NULL DEFAULT 'pending', |
| 37 | + "error" TEXT, |
| 38 | + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, |
| 39 | + CONSTRAINT "audit_anchors_pkey" PRIMARY KEY ("id") |
| 40 | +); |
| 41 | + |
| 42 | +CREATE INDEX IF NOT EXISTS "audit_anchors_latest_hash_idx" ON "audit_anchors"("latest_hash"); |
| 43 | +CREATE INDEX IF NOT EXISTS "audit_anchors_created_at_idx" ON "audit_anchors"("created_at"); |
| 44 | + |
| 45 | +CREATE TABLE IF NOT EXISTS "account_lockouts" ( |
| 46 | + "id" TEXT NOT NULL, |
| 47 | + "account_id" TEXT NOT NULL, |
| 48 | + "ip_address" TEXT, |
| 49 | + "failed_attempts" INTEGER NOT NULL DEFAULT 0, |
| 50 | + "locked_until" TIMESTAMP(3), |
| 51 | + "unlock_token_hash" TEXT, |
| 52 | + "last_failed_at" TIMESTAMP(3), |
| 53 | + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, |
| 54 | + "updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, |
| 55 | + CONSTRAINT "account_lockouts_pkey" PRIMARY KEY ("id") |
| 56 | +); |
| 57 | + |
| 58 | +CREATE UNIQUE INDEX IF NOT EXISTS "account_lockouts_account_id_ip_address_key" ON "account_lockouts"("account_id", "ip_address"); |
| 59 | +CREATE INDEX IF NOT EXISTS "account_lockouts_account_id_idx" ON "account_lockouts"("account_id"); |
| 60 | +CREATE INDEX IF NOT EXISTS "account_lockouts_ip_address_idx" ON "account_lockouts"("ip_address"); |
| 61 | +CREATE INDEX IF NOT EXISTS "account_lockouts_locked_until_idx" ON "account_lockouts"("locked_until"); |
| 62 | + |
| 63 | +CREATE TABLE IF NOT EXISTS "login_attempts" ( |
| 64 | + "id" TEXT NOT NULL, |
| 65 | + "account_id" TEXT NOT NULL, |
| 66 | + "ip_address" TEXT NOT NULL, |
| 67 | + "user_agent" TEXT, |
| 68 | + "success" BOOLEAN NOT NULL, |
| 69 | + "reason" TEXT, |
| 70 | + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, |
| 71 | + CONSTRAINT "login_attempts_pkey" PRIMARY KEY ("id") |
| 72 | +); |
| 73 | + |
| 74 | +CREATE INDEX IF NOT EXISTS "login_attempts_account_id_created_at_idx" ON "login_attempts"("account_id", "created_at"); |
| 75 | +CREATE INDEX IF NOT EXISTS "login_attempts_ip_address_created_at_idx" ON "login_attempts"("ip_address", "created_at"); |
| 76 | +CREATE INDEX IF NOT EXISTS "login_attempts_success_idx" ON "login_attempts"("success"); |
| 77 | + |
| 78 | +CREATE TABLE IF NOT EXISTS "webhook_secrets" ( |
| 79 | + "id" TEXT NOT NULL, |
| 80 | + "merchant_id" TEXT NOT NULL, |
| 81 | + "key_id" TEXT NOT NULL, |
| 82 | + "secret_hash" TEXT NOT NULL, |
| 83 | + "version" TEXT NOT NULL DEFAULT 'v1', |
| 84 | + "active_from" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, |
| 85 | + "expires_at" TIMESTAMP(3) NOT NULL, |
| 86 | + "rotated_at" TIMESTAMP(3), |
| 87 | + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, |
| 88 | + CONSTRAINT "webhook_secrets_pkey" PRIMARY KEY ("id") |
| 89 | +); |
| 90 | + |
| 91 | +CREATE UNIQUE INDEX IF NOT EXISTS "webhook_secrets_merchant_id_key_id_key" ON "webhook_secrets"("merchant_id", "key_id"); |
| 92 | +CREATE INDEX IF NOT EXISTS "webhook_secrets_merchant_id_expires_at_idx" ON "webhook_secrets"("merchant_id", "expires_at"); |
| 93 | + |
| 94 | +CREATE TABLE IF NOT EXISTS "vulnerability_reports" ( |
| 95 | + "id" TEXT NOT NULL, |
| 96 | + "source" TEXT NOT NULL, |
| 97 | + "scanned_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, |
| 98 | + "summary" JSONB NOT NULL, |
| 99 | + "artifact_url" TEXT, |
| 100 | + CONSTRAINT "vulnerability_reports_pkey" PRIMARY KEY ("id") |
| 101 | +); |
| 102 | + |
| 103 | +CREATE INDEX IF NOT EXISTS "vulnerability_reports_source_scanned_at_idx" ON "vulnerability_reports"("source", "scanned_at"); |
| 104 | + |
| 105 | +CREATE TABLE IF NOT EXISTS "dependency_vulnerabilities" ( |
| 106 | + "id" TEXT NOT NULL, |
| 107 | + "report_id" TEXT NOT NULL, |
| 108 | + "ecosystem" TEXT NOT NULL, |
| 109 | + "package_name" TEXT NOT NULL, |
| 110 | + "installed_version" TEXT, |
| 111 | + "fixed_version" TEXT, |
| 112 | + "severity" TEXT NOT NULL, |
| 113 | + "advisory_id" TEXT, |
| 114 | + "title" TEXT NOT NULL, |
| 115 | + "remediation" TEXT, |
| 116 | + "due_at" TIMESTAMP(3), |
| 117 | + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, |
| 118 | + CONSTRAINT "dependency_vulnerabilities_pkey" PRIMARY KEY ("id") |
| 119 | +); |
| 120 | + |
| 121 | +CREATE INDEX IF NOT EXISTS "dependency_vulnerabilities_ecosystem_severity_idx" ON "dependency_vulnerabilities"("ecosystem", "severity"); |
| 122 | +CREATE INDEX IF NOT EXISTS "dependency_vulnerabilities_package_name_idx" ON "dependency_vulnerabilities"("package_name"); |
| 123 | +ALTER TABLE "dependency_vulnerabilities" |
| 124 | + ADD CONSTRAINT "dependency_vulnerabilities_report_id_fkey" |
| 125 | + FOREIGN KEY ("report_id") REFERENCES "vulnerability_reports"("id") ON DELETE RESTRICT ON UPDATE CASCADE; |
0 commit comments