1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
//! SQL statements for waitpoint + HMAC secret ops
//! (RFC-023 Phase 2b.2.1).
//!
//! Mirrors `ff-backend-postgres/src/signal.rs` +
//! `ff-backend-postgres/src/suspend_ops.rs` at the statement level;
//! dialect deltas are the usual `jsonb → TEXT`, `$n → ?n`, no
//! `ON CONFLICT (cols) DO UPDATE SET col = EXCLUDED.col` array
//! binding (we bind lists via JSON strings where PG used `text[]`).
// ── HMAC keystore (ff_waitpoint_hmac) ─────────────────────────────────
pub const SELECT_ACTIVE_HMAC_SQL: &str = "SELECT kid, secret FROM ff_waitpoint_hmac \
WHERE active = 1 \
ORDER BY rotated_at_ms DESC LIMIT 1";
pub const SELECT_HMAC_SECRET_BY_KID_SQL: &str =
"SELECT secret FROM ff_waitpoint_hmac WHERE kid = ?1";
pub const DEACTIVATE_ALL_HMAC_SQL: &str =
"UPDATE ff_waitpoint_hmac SET active = 0 WHERE active = 1";
pub const INSERT_HMAC_ROW_SQL: &str = "INSERT INTO ff_waitpoint_hmac \
(kid, secret, rotated_at_ms, active) \
VALUES (?1, ?2, ?3, 1)";
pub const SELECT_ACTIVE_KID_SQL: &str = "SELECT kid FROM ff_waitpoint_hmac \
WHERE active = 1 \
ORDER BY rotated_at_ms DESC LIMIT 1";
// ── Pending waitpoint row (ff_waitpoint_pending) ──────────────────────
/// Insert-or-overwrite a waitpoint row. `required_signal_names` goes in
/// as a JSON-encoded TEXT column (SQLite has no native text[]).
/// Binds: 1=partition_key, 2=waitpoint_id, 3=execution_id,
/// 4=token_kid, 5=token, 6=created_at_ms, 7=expires_at_ms,
/// 8=waitpoint_key, 9=required_signal_names_json.
pub const UPSERT_WAITPOINT_PENDING_ACTIVE_SQL: &str = "INSERT INTO ff_waitpoint_pending \
(partition_key, waitpoint_id, execution_id, token_kid, token, \
created_at_ms, expires_at_ms, waitpoint_key, \
state, required_signal_names, activated_at_ms) \
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, 'active', ?9, ?6) \
ON CONFLICT (partition_key, waitpoint_id) DO UPDATE SET \
token_kid = excluded.token_kid, token = excluded.token, \
waitpoint_key = excluded.waitpoint_key, \
state = excluded.state, \
required_signal_names = excluded.required_signal_names, \
activated_at_ms = excluded.activated_at_ms";
/// Fresh pending-waitpoint row for `create_waitpoint` — state stays
/// `pending`, no `activated_at_ms`.
/// Binds: 1=partition, 2=waitpoint_id, 3=execution_id, 4=kid,
/// 5=token, 6=created_at_ms, 7=expires_at_ms, 8=waitpoint_key.
pub const INSERT_WAITPOINT_PENDING_SQL: &str = "INSERT INTO ff_waitpoint_pending \
(partition_key, waitpoint_id, execution_id, token_kid, token, \
created_at_ms, expires_at_ms, waitpoint_key, state, required_signal_names) \
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, 'pending', '[]')";
pub const SELECT_WAITPOINT_KEY_BY_ID_SQL: &str =
"SELECT waitpoint_key FROM ff_waitpoint_pending \
WHERE partition_key = ?1 AND waitpoint_id = ?2";
/// Point-read of a waitpoint's HMAC token, used by the signal-bridge
/// to authenticate signal-resume requests on SQLite deployments.
/// Binds: 1=partition_key (i64), 2=waitpoint_id (BLOB).
pub const SELECT_WAITPOINT_TOKEN_BY_ID_SQL: &str =
"SELECT token FROM ff_waitpoint_pending \
WHERE partition_key = ?1 AND waitpoint_id = ?2 LIMIT 1";
/// For deliver_signal: read kid + token + wp_key + bound execution.
/// Returns (token_kid, token, waitpoint_key, execution_id).
pub const SELECT_WAITPOINT_FOR_DELIVER_SQL: &str =
"SELECT token_kid, token, waitpoint_key, execution_id \
FROM ff_waitpoint_pending \
WHERE partition_key = ?1 AND waitpoint_id = ?2";
/// Delete every waitpoint row for a resolved execution.
pub const DELETE_WAITPOINTS_BY_EXEC_SQL: &str =
"DELETE FROM ff_waitpoint_pending \
WHERE partition_key = ?1 AND execution_id = ?2";
// ── list_pending_waitpoints (RFC-020 §4.5, Phase 3.3) ──────────────
/// Existence probe — matches PG reference's `EXISTS exec_core`
/// pre-check so a non-existent execution surfaces `NotFound` rather
/// than an empty page. Binds: ?1 partition_key, ?2 execution_id BLOB.
pub const SELECT_EXEC_EXISTS_SQL: &str =
"SELECT 1 FROM ff_exec_core WHERE partition_key = ?1 AND execution_id = ?2";
/// Cursor-paginated scan of `ff_waitpoint_pending` for one execution.
/// Filters to `state IN ('pending','active')` (matches Valkey's
/// client-side keep filter). Fetches `limit + 1` to detect "more to
/// come" without a second round-trip.
///
/// Binds:
/// 1. partition_key (i64)
/// 2. execution_id BLOB
/// 3. after_waitpoint_id BLOB — NULL → no cursor
/// 4. limit_plus_one (i64)
pub const SELECT_PENDING_WAITPOINTS_PAGE_SQL: &str =
"SELECT waitpoint_id, waitpoint_key, state, required_signal_names, \
created_at_ms, activated_at_ms, expires_at_ms, token_kid, token \
FROM ff_waitpoint_pending \
WHERE partition_key = ?1 \
AND execution_id = ?2 \
AND state IN ('pending', 'active') \
AND (?3 IS NULL OR waitpoint_id > ?3) \
ORDER BY waitpoint_id \
LIMIT ?4";