fix(backend): refresh draft.created_at on every upsert

The draft upsert was `ON CONFLICT (...) DO UPDATE SET value = EXCLUDED.value`,
so subsequent draft writes left `created_at` frozen at the first INSERT.
The frontend's UserDraft staleness check reads that timestamp as
`remoteDraftRev`; with it frozen, an updated remote draft looked
identical to the originally-baselined one and the "newer draft was
saved on the server" modal never fired.

Touch `created_at` on conflict too. The column's semantic widens from
"first write time" to "last write time", which is what every reader of
the field actually wants — the staleness signal is the only consumer.

SQLx offline cache regenerated to match the new query text.
This commit is contained in:
Diego Imbert
2026-05-15 01:43:09 +02:00
parent a9939af90a
commit d1f102d750
11 changed files with 528 additions and 7 deletions
@@ -0,0 +1,94 @@
{
"db_name": "PostgreSQL",
"query": "SELECT email, login_type::TEXT, super_admin, devops, verified, name, company, username, NULL::bool as operator_only, first_time_user, role_source, disabled, NULL::text as workspace_id FROM password WHERE email = $1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "email",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "login_type",
"type_info": "Text"
},
{
"ordinal": 2,
"name": "super_admin",
"type_info": "Bool"
},
{
"ordinal": 3,
"name": "devops",
"type_info": "Bool"
},
{
"ordinal": 4,
"name": "verified",
"type_info": "Bool"
},
{
"ordinal": 5,
"name": "name",
"type_info": "Varchar"
},
{
"ordinal": 6,
"name": "company",
"type_info": "Varchar"
},
{
"ordinal": 7,
"name": "username",
"type_info": "Varchar"
},
{
"ordinal": 8,
"name": "operator_only",
"type_info": "Bool"
},
{
"ordinal": 9,
"name": "first_time_user",
"type_info": "Bool"
},
{
"ordinal": 10,
"name": "role_source",
"type_info": "Varchar"
},
{
"ordinal": 11,
"name": "disabled",
"type_info": "Bool"
},
{
"ordinal": 12,
"name": "workspace_id",
"type_info": "Text"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
false,
null,
false,
false,
false,
true,
true,
true,
null,
false,
false,
false,
null
]
},
"hash": "0142d9dc9c1b57487dd5709a0376794f18d33e5bd6340c0189be7818cda64328"
}
@@ -46,11 +46,11 @@
]
},
"nullable": [
false,
false,
false,
false,
false,
true,
true,
true,
true,
true,
true,
true
]
@@ -0,0 +1,95 @@
{
"db_name": "PostgreSQL",
"query": "SELECT email as \"email!\", login_type::text, verified as \"verified!\", super_admin as \"super_admin!\", devops as \"devops!\", name, company, username, NULL::bool as operator_only, first_time_user as \"first_time_user!\", role_source as \"role_source!\", disabled as \"disabled!\", NULL::text as workspace_id FROM password\n UNION ALL\n SELECT email as \"email!\", 'service_account'::text as login_type, true as \"verified!\", false as \"super_admin!\", false as \"devops!\", NULL::text as name, NULL::text as company, username, true as operator_only, false as \"first_time_user!\", 'service_account'::text as \"role_source!\", disabled as \"disabled!\", workspace_id\n FROM usr\n WHERE is_service_account IS true\n ORDER BY \"super_admin!\" DESC, \"devops!\" DESC, \"email!\"\n LIMIT $1 OFFSET $2",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "email!",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "login_type",
"type_info": "Text"
},
{
"ordinal": 2,
"name": "verified!",
"type_info": "Bool"
},
{
"ordinal": 3,
"name": "super_admin!",
"type_info": "Bool"
},
{
"ordinal": 4,
"name": "devops!",
"type_info": "Bool"
},
{
"ordinal": 5,
"name": "name",
"type_info": "Varchar"
},
{
"ordinal": 6,
"name": "company",
"type_info": "Varchar"
},
{
"ordinal": 7,
"name": "username",
"type_info": "Varchar"
},
{
"ordinal": 8,
"name": "operator_only",
"type_info": "Bool"
},
{
"ordinal": 9,
"name": "first_time_user!",
"type_info": "Bool"
},
{
"ordinal": 10,
"name": "role_source!",
"type_info": "Varchar"
},
{
"ordinal": 11,
"name": "disabled!",
"type_info": "Bool"
},
{
"ordinal": 12,
"name": "workspace_id",
"type_info": "Text"
}
],
"parameters": {
"Left": [
"Int8",
"Int8"
]
},
"nullable": [
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
]
},
"hash": "16b4496c21d0619dab4521dca22e5fe144c59156a8f06d8592291684c49b2f37"
}
@@ -0,0 +1,28 @@
{
"db_name": "PostgreSQL",
"query": "INSERT INTO draft\n (workspace_id, path, value, typ)\n VALUES ($1, $2, $3::text::json, $4)\n ON CONFLICT (workspace_id, path, typ)\n DO UPDATE SET value = EXCLUDED.value, created_at = now()",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"Varchar",
"Text",
{
"Custom": {
"name": "draft_type",
"kind": {
"Enum": [
"script",
"flow",
"app"
]
}
}
}
]
},
"nullable": []
},
"hash": "5104cf045dc9b7b82d0028af11cfb5c2f6fd58e518085caf8e8d189951f7c4d8"
}
@@ -0,0 +1,66 @@
{
"db_name": "PostgreSQL",
"query": "SELECT label, token_prefix, expiration, created_at, last_used_at, scopes, workspace_id, read_only FROM token WHERE email = $1\n ORDER BY created_at DESC LIMIT $2 OFFSET $3",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "label",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "token_prefix",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "expiration",
"type_info": "Timestamptz"
},
{
"ordinal": 3,
"name": "created_at",
"type_info": "Timestamptz"
},
{
"ordinal": 4,
"name": "last_used_at",
"type_info": "Timestamptz"
},
{
"ordinal": 5,
"name": "scopes",
"type_info": "TextArray"
},
{
"ordinal": 6,
"name": "workspace_id",
"type_info": "Varchar"
},
{
"ordinal": 7,
"name": "read_only",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Text",
"Int8",
"Int8"
]
},
"nullable": [
true,
false,
true,
false,
false,
true,
true,
false
]
},
"hash": "52777947d60d5ddd6d28852a1cf104a5af2fd565706204b7d5d33594ff91e61e"
}
@@ -15,7 +15,7 @@
]
},
"nullable": [
true
null
]
},
"hash": "5a219a2532517869578c4504ff3153c43903f929ae5d62fbba12610f89c36d55"
@@ -0,0 +1,23 @@
{
"db_name": "PostgreSQL",
"query": "INSERT INTO token\n (token_hash, token_prefix, token, email, label, expiration, super_admin, scopes, workspace_id, read_only)\n SELECT $1, $2, $3, $4, $5, $6, $7, $8, $9, $10\n WHERE $9::varchar IS NULL OR NOT EXISTS(\n SELECT 1 FROM workspace WHERE id = $9 AND deleted = true\n )",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"Varchar",
"Varchar",
"Varchar",
"Varchar",
"Timestamptz",
"Bool",
"TextArray",
"Varchar",
"Bool"
]
},
"nullable": []
},
"hash": "9a1bf7c424154172b56bbd29b51ef468969b5452150ee6fffe31d59b52a4f1c2"
}
@@ -0,0 +1,95 @@
{
"db_name": "PostgreSQL",
"query": "WITH active_users AS (SELECT distinct username as email FROM (SELECT username, timestamp, operation FROM audit_partitioned UNION ALL SELECT username, timestamp, operation FROM audit) AS a WHERE timestamp > NOW() - INTERVAL '1 month' AND (operation = 'users.login' OR operation = 'oauth.login' OR operation = 'users.token.refresh')),\n authors as (SELECT distinct email FROM usr WHERE usr.operator IS false)\n SELECT email as \"email!\", (email NOT IN (SELECT email FROM authors)) as operator_only, login_type::text, verified as \"verified!\", super_admin as \"super_admin!\", devops as \"devops!\", name, company, username, first_time_user as \"first_time_user!\", role_source as \"role_source!\", disabled as \"disabled!\", NULL::text as workspace_id\n FROM password\n WHERE email IN (SELECT email FROM active_users)\n UNION ALL\n SELECT email as \"email!\", true as operator_only, 'service_account'::text as login_type, true as \"verified!\", false as \"super_admin!\", false as \"devops!\", NULL::text as name, NULL::text as company, username, false as \"first_time_user!\", 'service_account'::text as \"role_source!\", disabled as \"disabled!\", workspace_id\n FROM usr\n WHERE is_service_account IS true\n ORDER BY \"super_admin!\" DESC, \"devops!\" DESC\n LIMIT $1 OFFSET $2",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "email!",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "operator_only",
"type_info": "Bool"
},
{
"ordinal": 2,
"name": "login_type",
"type_info": "Text"
},
{
"ordinal": 3,
"name": "verified!",
"type_info": "Bool"
},
{
"ordinal": 4,
"name": "super_admin!",
"type_info": "Bool"
},
{
"ordinal": 5,
"name": "devops!",
"type_info": "Bool"
},
{
"ordinal": 6,
"name": "name",
"type_info": "Varchar"
},
{
"ordinal": 7,
"name": "company",
"type_info": "Varchar"
},
{
"ordinal": 8,
"name": "username",
"type_info": "Varchar"
},
{
"ordinal": 9,
"name": "first_time_user!",
"type_info": "Bool"
},
{
"ordinal": 10,
"name": "role_source!",
"type_info": "Varchar"
},
{
"ordinal": 11,
"name": "disabled!",
"type_info": "Bool"
},
{
"ordinal": 12,
"name": "workspace_id",
"type_info": "Text"
}
],
"parameters": {
"Left": [
"Int8",
"Int8"
]
},
"nullable": [
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
]
},
"hash": "c17c39add3f70218dbae38595a909d02cfabe7e0864af577df6968428ac448ef"
}
@@ -0,0 +1,66 @@
{
"db_name": "PostgreSQL",
"query": "SELECT label, token_prefix, expiration, created_at, last_used_at, scopes, workspace_id, read_only FROM token WHERE email = $1 AND (label != 'ephemeral-script' OR label IS NULL)\n ORDER BY created_at DESC LIMIT $2 OFFSET $3",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "label",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "token_prefix",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "expiration",
"type_info": "Timestamptz"
},
{
"ordinal": 3,
"name": "created_at",
"type_info": "Timestamptz"
},
{
"ordinal": 4,
"name": "last_used_at",
"type_info": "Timestamptz"
},
{
"ordinal": 5,
"name": "scopes",
"type_info": "TextArray"
},
{
"ordinal": 6,
"name": "workspace_id",
"type_info": "Varchar"
},
{
"ordinal": 7,
"name": "read_only",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Text",
"Int8",
"Int8"
]
},
"nullable": [
true,
false,
true,
false,
false,
true,
true,
false
]
},
"hash": "e001fb68c60fa736cecce52be49c9fb0714c9c91a7ea3924811d345bee94c013"
}
@@ -0,0 +1,53 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE token SET last_used_at = now() WHERE\n token_hash = $1\n AND (expiration > NOW() OR expiration IS NULL)\n AND (workspace_id IS NULL OR workspace_id = $2)\n RETURNING owner, email, super_admin, scopes, label, read_only",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "owner",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "email",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "super_admin",
"type_info": "Bool"
},
{
"ordinal": 3,
"name": "scopes",
"type_info": "TextArray"
},
{
"ordinal": 4,
"name": "label",
"type_info": "Varchar"
},
{
"ordinal": 5,
"name": "read_only",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
true,
true,
false,
true,
true,
false
]
},
"hash": "ed82ffc4d806a19519701e39abc43e8e250cc9772cca4a7dae3442be86f4060c"
}
+2 -1
View File
@@ -79,7 +79,8 @@ async fn create_draft(
"INSERT INTO draft
(workspace_id, path, value, typ)
VALUES ($1, $2, $3::text::json, $4)
ON CONFLICT (workspace_id, path, typ) DO UPDATE SET value = EXCLUDED.value",
ON CONFLICT (workspace_id, path, typ)
DO UPDATE SET value = EXCLUDED.value, created_at = now()",
&w_id,
draft.path,
//to preserve key orders