feat(website-intake): dual-write endpoint + migration chain repair
Adds website_submissions table + shared-secret POST endpoint so the marketing site can dual-write inquiries alongside its NocoDB write. Race-safe via INSERT ... ON CONFLICT, idempotent on submission_id, refuses every request when WEBSITE_INTAKE_SECRET is unset. Also repairs pre-existing 0020/0021/0022 prevId collision (renumbered + journal re-sorted) so db:generate works again. 11 unit tests. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"id": "e0e6a819-cf9f-45d3-b65b-19da27890f0b",
|
||||
"id": "e9d830fc-ec81-42ab-bea6-232dd99d20d1",
|
||||
"prevId": "6326a9a7-0b30-4647-bf86-b3d79e6a08bf",
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
@@ -762,13 +762,13 @@
|
||||
},
|
||||
"nominal_boat_size": {
|
||||
"name": "nominal_boat_size",
|
||||
"type": "numeric",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"nominal_boat_size_m": {
|
||||
"name": "nominal_boat_size_m",
|
||||
"type": "numeric",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
@@ -799,13 +799,13 @@
|
||||
},
|
||||
"power_capacity": {
|
||||
"name": "power_capacity",
|
||||
"type": "numeric",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"voltage": {
|
||||
"name": "voltage",
|
||||
"type": "numeric",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
@@ -914,12 +914,6 @@
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"status_override_mode": {
|
||||
"name": "status_override_mode",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
@@ -1339,6 +1333,158 @@
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.client_merge_candidates": {
|
||||
"name": "client_merge_candidates",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true
|
||||
},
|
||||
"port_id": {
|
||||
"name": "port_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"client_a_id": {
|
||||
"name": "client_a_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"client_b_id": {
|
||||
"name": "client_b_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"score": {
|
||||
"name": "score",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"reasons": {
|
||||
"name": "reasons",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"status": {
|
||||
"name": "status",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'pending'"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"resolved_at": {
|
||||
"name": "resolved_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"resolved_by": {
|
||||
"name": "resolved_by",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"idx_cmc_port_status": {
|
||||
"name": "idx_cmc_port_status",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "port_id",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
},
|
||||
{
|
||||
"expression": "status",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
},
|
||||
"idx_cmc_pair": {
|
||||
"name": "idx_cmc_pair",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "port_id",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
},
|
||||
{
|
||||
"expression": "client_a_id",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
},
|
||||
{
|
||||
"expression": "client_b_id",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": true,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"client_merge_candidates_port_id_ports_id_fk": {
|
||||
"name": "client_merge_candidates_port_id_ports_id_fk",
|
||||
"tableFrom": "client_merge_candidates",
|
||||
"tableTo": "ports",
|
||||
"columnsFrom": ["port_id"],
|
||||
"columnsTo": ["id"],
|
||||
"onDelete": "no action",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"client_merge_candidates_client_a_id_clients_id_fk": {
|
||||
"name": "client_merge_candidates_client_a_id_clients_id_fk",
|
||||
"tableFrom": "client_merge_candidates",
|
||||
"tableTo": "clients",
|
||||
"columnsFrom": ["client_a_id"],
|
||||
"columnsTo": ["id"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"client_merge_candidates_client_b_id_clients_id_fk": {
|
||||
"name": "client_merge_candidates_client_b_id_clients_id_fk",
|
||||
"tableFrom": "client_merge_candidates",
|
||||
"tableTo": "clients",
|
||||
"columnsFrom": ["client_b_id"],
|
||||
"columnsTo": ["id"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.client_merge_log": {
|
||||
"name": "client_merge_log",
|
||||
"schema": "",
|
||||
@@ -10230,6 +10376,96 @@
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.migration_source_links": {
|
||||
"name": "migration_source_links",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true
|
||||
},
|
||||
"source_system": {
|
||||
"name": "source_system",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"source_id": {
|
||||
"name": "source_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"target_entity_type": {
|
||||
"name": "target_entity_type",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"target_entity_id": {
|
||||
"name": "target_entity_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"applied_id": {
|
||||
"name": "applied_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"applied_by": {
|
||||
"name": "applied_by",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"applied_at": {
|
||||
"name": "applied_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"idx_msl_source_target": {
|
||||
"name": "idx_msl_source_target",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "source_system",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
},
|
||||
{
|
||||
"expression": "source_id",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
},
|
||||
{
|
||||
"expression": "target_entity_type",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": true,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
}
|
||||
},
|
||||
"enums": {},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"id": "e9d830fc-ec81-42ab-bea6-232dd99d20d1",
|
||||
"prevId": "6326a9a7-0b30-4647-bf86-b3d79e6a08bf",
|
||||
"id": "9f6ae433-f075-4348-8109-3cd368344fa8",
|
||||
"prevId": "e9d830fc-ec81-42ab-bea6-232dd99d20d1",
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"tables": {
|
||||
@@ -1870,6 +1870,12 @@
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"merged_into_client_id": {
|
||||
"name": "merged_into_client_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
@@ -1957,6 +1963,21 @@
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
},
|
||||
"idx_clients_merged_into": {
|
||||
"name": "idx_clients_merged_into",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "merged_into_client_id",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"id": "9f6ae433-f075-4348-8109-3cd368344fa8",
|
||||
"prevId": "e9d830fc-ec81-42ab-bea6-232dd99d20d1",
|
||||
"id": "e0e6a819-cf9f-45d3-b65b-19da27890f0b",
|
||||
"prevId": "9f6ae433-f075-4348-8109-3cd368344fa8",
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"tables": {
|
||||
@@ -762,13 +762,13 @@
|
||||
},
|
||||
"nominal_boat_size": {
|
||||
"name": "nominal_boat_size",
|
||||
"type": "text",
|
||||
"type": "numeric",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"nominal_boat_size_m": {
|
||||
"name": "nominal_boat_size_m",
|
||||
"type": "text",
|
||||
"type": "numeric",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
@@ -799,13 +799,13 @@
|
||||
},
|
||||
"power_capacity": {
|
||||
"name": "power_capacity",
|
||||
"type": "text",
|
||||
"type": "numeric",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"voltage": {
|
||||
"name": "voltage",
|
||||
"type": "text",
|
||||
"type": "numeric",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
@@ -914,6 +914,12 @@
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"status_override_mode": {
|
||||
"name": "status_override_mode",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
|
||||
10639
src/lib/db/migrations/meta/0023_snapshot.json
Normal file
10639
src/lib/db/migrations/meta/0023_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -145,22 +145,29 @@
|
||||
{
|
||||
"idx": 20,
|
||||
"version": "7",
|
||||
"when": 1777814682110,
|
||||
"tag": "0020_medical_betty_brant",
|
||||
"when": 1777811835982,
|
||||
"tag": "0020_unusual_azazel",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 21,
|
||||
"version": "7",
|
||||
"when": 1777811835982,
|
||||
"tag": "0021_unusual_azazel",
|
||||
"when": 1777812671833,
|
||||
"tag": "0021_magenta_madame_hydra",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 22,
|
||||
"version": "7",
|
||||
"when": 1777812671833,
|
||||
"tag": "0022_magenta_madame_hydra",
|
||||
"when": 1777814682110,
|
||||
"tag": "0022_medical_betty_brant",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 23,
|
||||
"version": "7",
|
||||
"when": 1777927586934,
|
||||
"tag": "0023_omniscient_reaper",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user