@team-semicolon/semicolony-cli 4.18.51 → 4.18.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundle.js +1524 -1046
- package/migrations/149_hive_cron_capability_templates.sql +44 -0
- package/migrations/150_hive_cron_action_contract.sql +38 -0
- package/migrations/151_hive_cron_occurrence_leases.sql +150 -0
- package/migrations/152_hive_cron_relay_outbox.sql +243 -0
- package/migrations/153_hive_cron_evidence_uniqueness.sql +9 -0
- package/migrations/154_hive_cron_evidence_provider_grants.sql +816 -0
- package/migrations/155_hive_cron_occurrence_lease_provider_grants.sql +44 -0
- package/migrations/156_hive_cron_relay_outbox_provider_grants.sql +47 -0
- package/migrations/157_hive_cron_trusted_config_revisions.sql +243 -0
- package/migrations/158_hive_cron_typed_dispatch_outbox.sql +1406 -0
- package/migrations/159_hive_cron_shadow_cursor.sql +600 -0
- package/migrations/160_hive_cron_failure_alert_outbox.sql +406 -0
- package/migrations/161_skill_governance.sql +529 -0
- package/migrations/161_workspace_projection_grants.sql +39 -0
- package/migrations/162_sc_app_kb_history_trigger_hardening.sql +96 -0
- package/migrations/163_workspace_projection_grants_sc_app_read.sql +21 -0
- package/package.json +4 -2
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
-- @schema-retarget: off
|
|
2
|
+
-- Durable, credential-free Hive cron failure-alert authority.
|
|
3
|
+
-- The migration runner supplies the transaction boundary; do not add one here.
|
|
4
|
+
|
|
5
|
+
DO $$
|
|
6
|
+
DECLARE
|
|
7
|
+
role_state record;
|
|
8
|
+
BEGIN
|
|
9
|
+
SELECT rolcanlogin, rolsuper, rolcreatedb, rolcreaterole,
|
|
10
|
+
rolinherit, rolreplication, rolbypassrls
|
|
11
|
+
INTO role_state
|
|
12
|
+
FROM pg_catalog.pg_roles
|
|
13
|
+
WHERE rolname = 'sc_provider';
|
|
14
|
+
|
|
15
|
+
IF NOT FOUND THEN
|
|
16
|
+
RAISE EXCEPTION 'sc_provider role missing; migration 135 required';
|
|
17
|
+
END IF;
|
|
18
|
+
|
|
19
|
+
IF NOT role_state.rolcanlogin
|
|
20
|
+
OR role_state.rolsuper
|
|
21
|
+
OR role_state.rolcreatedb
|
|
22
|
+
OR role_state.rolcreaterole
|
|
23
|
+
OR role_state.rolinherit
|
|
24
|
+
OR role_state.rolreplication
|
|
25
|
+
OR role_state.rolbypassrls THEN
|
|
26
|
+
RAISE EXCEPTION 'sc_provider role attributes are unsafe';
|
|
27
|
+
END IF;
|
|
28
|
+
END $$;
|
|
29
|
+
|
|
30
|
+
CREATE TABLE semicolony.cron_read_action_failure_alert_outbox (
|
|
31
|
+
occurrence_key TEXT PRIMARY KEY,
|
|
32
|
+
failure_code TEXT NOT NULL CHECK (
|
|
33
|
+
failure_code IN ('released_failed', 'retry_exhausted', 'stale_binding')
|
|
34
|
+
),
|
|
35
|
+
state TEXT NOT NULL DEFAULT 'pending' CHECK (
|
|
36
|
+
state IN ('pending', 'claimed', 'sent', 'failed', 'ambiguous')
|
|
37
|
+
),
|
|
38
|
+
claim_id TEXT UNIQUE CHECK (
|
|
39
|
+
claim_id IS NULL
|
|
40
|
+
OR (claim_id COLLATE "C") ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
|
|
41
|
+
),
|
|
42
|
+
claimed_at TIMESTAMPTZ,
|
|
43
|
+
claim_expires_at TIMESTAMPTZ,
|
|
44
|
+
resolved_at TIMESTAMPTZ,
|
|
45
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT pg_catalog.clock_timestamp(),
|
|
46
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT pg_catalog.clock_timestamp(),
|
|
47
|
+
FOREIGN KEY (occurrence_key)
|
|
48
|
+
REFERENCES semicolony.cron_read_action_dispatch_outbox (idempotency_key),
|
|
49
|
+
CHECK (
|
|
50
|
+
(
|
|
51
|
+
state = 'pending'
|
|
52
|
+
AND claim_id IS NULL
|
|
53
|
+
AND claimed_at IS NULL
|
|
54
|
+
AND claim_expires_at IS NULL
|
|
55
|
+
AND resolved_at IS NULL
|
|
56
|
+
)
|
|
57
|
+
OR
|
|
58
|
+
(
|
|
59
|
+
state = 'claimed'
|
|
60
|
+
AND claim_id IS NOT NULL
|
|
61
|
+
AND claimed_at IS NOT NULL
|
|
62
|
+
AND claim_expires_at IS NOT NULL
|
|
63
|
+
AND claim_expires_at > claimed_at
|
|
64
|
+
AND resolved_at IS NULL
|
|
65
|
+
)
|
|
66
|
+
OR
|
|
67
|
+
(
|
|
68
|
+
state IN ('sent', 'failed', 'ambiguous')
|
|
69
|
+
AND claim_id IS NOT NULL
|
|
70
|
+
AND claimed_at IS NOT NULL
|
|
71
|
+
AND claim_expires_at IS NOT NULL
|
|
72
|
+
AND claim_expires_at > claimed_at
|
|
73
|
+
AND resolved_at IS NOT NULL
|
|
74
|
+
)
|
|
75
|
+
)
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
CREATE INDEX idx_cron_read_action_failure_alert_pending
|
|
79
|
+
ON semicolony.cron_read_action_failure_alert_outbox (created_at, occurrence_key)
|
|
80
|
+
WHERE state = 'pending';
|
|
81
|
+
|
|
82
|
+
CREATE INDEX idx_cron_read_action_failure_alert_expired
|
|
83
|
+
ON semicolony.cron_read_action_failure_alert_outbox (claim_expires_at, occurrence_key)
|
|
84
|
+
WHERE state = 'claimed';
|
|
85
|
+
|
|
86
|
+
CREATE FUNCTION semicolony.hive_cron_protect_failure_alert()
|
|
87
|
+
RETURNS trigger
|
|
88
|
+
LANGUAGE plpgsql
|
|
89
|
+
SECURITY DEFINER
|
|
90
|
+
SET search_path = pg_catalog
|
|
91
|
+
SET TimeZone = 'UTC'
|
|
92
|
+
AS $$
|
|
93
|
+
BEGIN
|
|
94
|
+
IF TG_OP = 'DELETE' THEN
|
|
95
|
+
RAISE EXCEPTION 'failure_alert_delete_denied' USING ERRCODE = '55000';
|
|
96
|
+
END IF;
|
|
97
|
+
|
|
98
|
+
IF NEW.occurrence_key IS DISTINCT FROM OLD.occurrence_key
|
|
99
|
+
OR NEW.failure_code IS DISTINCT FROM OLD.failure_code
|
|
100
|
+
OR NEW.created_at IS DISTINCT FROM OLD.created_at THEN
|
|
101
|
+
RAISE EXCEPTION 'failure_alert_identity_immutable' USING ERRCODE = '55000';
|
|
102
|
+
END IF;
|
|
103
|
+
|
|
104
|
+
IF OLD.state IN ('sent', 'failed', 'ambiguous') THEN
|
|
105
|
+
RAISE EXCEPTION 'failure_alert_terminal_immutable' USING ERRCODE = '55000';
|
|
106
|
+
END IF;
|
|
107
|
+
|
|
108
|
+
IF OLD.state = 'pending' AND NEW.state <> 'claimed' THEN
|
|
109
|
+
RAISE EXCEPTION 'invalid_failure_alert_transition' USING ERRCODE = '55000';
|
|
110
|
+
END IF;
|
|
111
|
+
|
|
112
|
+
IF OLD.state = 'claimed' AND NEW.state NOT IN ('sent', 'failed', 'ambiguous') THEN
|
|
113
|
+
RAISE EXCEPTION 'invalid_failure_alert_transition' USING ERRCODE = '55000';
|
|
114
|
+
END IF;
|
|
115
|
+
|
|
116
|
+
RETURN NEW;
|
|
117
|
+
END;
|
|
118
|
+
$$;
|
|
119
|
+
|
|
120
|
+
CREATE TRIGGER protect_cron_read_action_failure_alert
|
|
121
|
+
BEFORE UPDATE OR DELETE ON semicolony.cron_read_action_failure_alert_outbox
|
|
122
|
+
FOR EACH ROW EXECUTE FUNCTION semicolony.hive_cron_protect_failure_alert();
|
|
123
|
+
|
|
124
|
+
CREATE FUNCTION semicolony.hive_cron_record_failure_alert()
|
|
125
|
+
RETURNS trigger
|
|
126
|
+
LANGUAGE plpgsql
|
|
127
|
+
SECURITY DEFINER
|
|
128
|
+
SET search_path = pg_catalog
|
|
129
|
+
SET TimeZone = 'UTC'
|
|
130
|
+
AS $$
|
|
131
|
+
DECLARE
|
|
132
|
+
failure_count integer;
|
|
133
|
+
BEGIN
|
|
134
|
+
IF OLD.status IS DISTINCT FROM 'failed'
|
|
135
|
+
AND NEW.status = 'failed'
|
|
136
|
+
AND NEW.result_code IN ('released_failed', 'retry_exhausted', 'stale_binding') THEN
|
|
137
|
+
UPDATE semicolony.bot_cron_jobs AS job
|
|
138
|
+
SET consecutive_failures = job.consecutive_failures + 1,
|
|
139
|
+
last_status = 'failure',
|
|
140
|
+
last_error = NEW.result_code,
|
|
141
|
+
last_run = NEW.resolved_at
|
|
142
|
+
WHERE job.bot_id = 'semi'
|
|
143
|
+
AND job.job_id = NEW.job_id
|
|
144
|
+
AND job.runtime_source = 'hive-cron-v2'
|
|
145
|
+
RETURNING job.consecutive_failures INTO failure_count;
|
|
146
|
+
|
|
147
|
+
IF NOT FOUND THEN
|
|
148
|
+
RAISE EXCEPTION 'failure_alert_job_authority_missing' USING ERRCODE = 'P0001';
|
|
149
|
+
END IF;
|
|
150
|
+
|
|
151
|
+
IF failure_count = 3 THEN
|
|
152
|
+
INSERT INTO semicolony.cron_read_action_failure_alert_outbox (
|
|
153
|
+
occurrence_key, failure_code
|
|
154
|
+
) VALUES (
|
|
155
|
+
NEW.idempotency_key, NEW.result_code
|
|
156
|
+
);
|
|
157
|
+
END IF;
|
|
158
|
+
END IF;
|
|
159
|
+
|
|
160
|
+
RETURN NEW;
|
|
161
|
+
END;
|
|
162
|
+
$$;
|
|
163
|
+
|
|
164
|
+
CREATE TRIGGER record_hive_cron_failure_alert
|
|
165
|
+
AFTER UPDATE ON semicolony.cron_read_action_dispatch_outbox
|
|
166
|
+
FOR EACH ROW
|
|
167
|
+
WHEN (
|
|
168
|
+
OLD.status IS DISTINCT FROM 'failed'
|
|
169
|
+
AND NEW.status = 'failed'
|
|
170
|
+
AND NEW.result_code IN ('released_failed', 'retry_exhausted', 'stale_binding')
|
|
171
|
+
)
|
|
172
|
+
EXECUTE FUNCTION semicolony.hive_cron_record_failure_alert();
|
|
173
|
+
|
|
174
|
+
CREATE FUNCTION semicolony.hive_cron_claim_failure_alert(
|
|
175
|
+
p_claim_id text,
|
|
176
|
+
p_lease_seconds integer
|
|
177
|
+
)
|
|
178
|
+
RETURNS TABLE (
|
|
179
|
+
outcome text,
|
|
180
|
+
occurrence_key text,
|
|
181
|
+
failure_code text,
|
|
182
|
+
claim_id text,
|
|
183
|
+
claimed_at timestamptz,
|
|
184
|
+
claim_expires_at timestamptz,
|
|
185
|
+
resolved_at timestamptz
|
|
186
|
+
)
|
|
187
|
+
LANGUAGE plpgsql
|
|
188
|
+
SECURITY DEFINER
|
|
189
|
+
SET search_path = pg_catalog
|
|
190
|
+
SET TimeZone = 'UTC'
|
|
191
|
+
AS $$
|
|
192
|
+
DECLARE
|
|
193
|
+
alert record;
|
|
194
|
+
db_now timestamptz;
|
|
195
|
+
BEGIN
|
|
196
|
+
IF session_user <> 'sc_provider'
|
|
197
|
+
OR public.is_provider() IS DISTINCT FROM true THEN
|
|
198
|
+
RAISE EXCEPTION 'provider_mode_required' USING ERRCODE = '42501';
|
|
199
|
+
END IF;
|
|
200
|
+
|
|
201
|
+
IF p_claim_id IS NULL
|
|
202
|
+
OR (p_claim_id COLLATE "C") !~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
|
|
203
|
+
OR p_lease_seconds IS NULL
|
|
204
|
+
OR p_lease_seconds NOT BETWEEN 1 AND 3600 THEN
|
|
205
|
+
RAISE EXCEPTION 'invalid_failure_alert_claim' USING ERRCODE = '22023';
|
|
206
|
+
END IF;
|
|
207
|
+
|
|
208
|
+
PERFORM pg_catalog.pg_advisory_xact_lock(
|
|
209
|
+
pg_catalog.hashtextextended(p_claim_id, 0::bigint)
|
|
210
|
+
);
|
|
211
|
+
db_now := pg_catalog.clock_timestamp();
|
|
212
|
+
|
|
213
|
+
SELECT current_alert.occurrence_key,
|
|
214
|
+
current_alert.failure_code,
|
|
215
|
+
current_alert.state,
|
|
216
|
+
current_alert.claim_id,
|
|
217
|
+
current_alert.claimed_at,
|
|
218
|
+
current_alert.claim_expires_at,
|
|
219
|
+
current_alert.resolved_at
|
|
220
|
+
INTO alert
|
|
221
|
+
FROM semicolony.cron_read_action_failure_alert_outbox AS current_alert
|
|
222
|
+
WHERE current_alert.claim_id = p_claim_id
|
|
223
|
+
FOR UPDATE;
|
|
224
|
+
|
|
225
|
+
IF FOUND THEN
|
|
226
|
+
IF alert.state = 'claimed' AND alert.claim_expires_at <= db_now THEN
|
|
227
|
+
UPDATE semicolony.cron_read_action_failure_alert_outbox AS current_alert
|
|
228
|
+
SET state = 'ambiguous',
|
|
229
|
+
resolved_at = db_now,
|
|
230
|
+
updated_at = db_now
|
|
231
|
+
WHERE current_alert.occurrence_key = alert.occurrence_key;
|
|
232
|
+
|
|
233
|
+
RETURN QUERY SELECT
|
|
234
|
+
'recovered_ambiguous'::text,
|
|
235
|
+
alert.occurrence_key,
|
|
236
|
+
alert.failure_code,
|
|
237
|
+
alert.claim_id,
|
|
238
|
+
alert.claimed_at,
|
|
239
|
+
alert.claim_expires_at,
|
|
240
|
+
db_now;
|
|
241
|
+
ELSE
|
|
242
|
+
RETURN QUERY SELECT
|
|
243
|
+
'claim_exists'::text,
|
|
244
|
+
alert.occurrence_key,
|
|
245
|
+
alert.failure_code,
|
|
246
|
+
alert.claim_id,
|
|
247
|
+
alert.claimed_at,
|
|
248
|
+
alert.claim_expires_at,
|
|
249
|
+
alert.resolved_at;
|
|
250
|
+
END IF;
|
|
251
|
+
RETURN;
|
|
252
|
+
END IF;
|
|
253
|
+
|
|
254
|
+
SELECT current_alert.occurrence_key,
|
|
255
|
+
current_alert.failure_code,
|
|
256
|
+
current_alert.claim_id,
|
|
257
|
+
current_alert.claimed_at,
|
|
258
|
+
current_alert.claim_expires_at
|
|
259
|
+
INTO alert
|
|
260
|
+
FROM semicolony.cron_read_action_failure_alert_outbox AS current_alert
|
|
261
|
+
WHERE current_alert.state = 'claimed'
|
|
262
|
+
AND current_alert.claim_expires_at <= db_now
|
|
263
|
+
ORDER BY current_alert.claim_expires_at, current_alert.occurrence_key
|
|
264
|
+
LIMIT 1
|
|
265
|
+
FOR UPDATE;
|
|
266
|
+
|
|
267
|
+
IF FOUND THEN
|
|
268
|
+
UPDATE semicolony.cron_read_action_failure_alert_outbox AS current_alert
|
|
269
|
+
SET state = 'ambiguous',
|
|
270
|
+
resolved_at = db_now,
|
|
271
|
+
updated_at = db_now
|
|
272
|
+
WHERE current_alert.occurrence_key = alert.occurrence_key;
|
|
273
|
+
|
|
274
|
+
RETURN QUERY SELECT
|
|
275
|
+
'recovered_ambiguous'::text,
|
|
276
|
+
alert.occurrence_key,
|
|
277
|
+
alert.failure_code,
|
|
278
|
+
alert.claim_id,
|
|
279
|
+
alert.claimed_at,
|
|
280
|
+
alert.claim_expires_at,
|
|
281
|
+
db_now;
|
|
282
|
+
RETURN;
|
|
283
|
+
END IF;
|
|
284
|
+
|
|
285
|
+
SELECT current_alert.occurrence_key,
|
|
286
|
+
current_alert.failure_code
|
|
287
|
+
INTO alert
|
|
288
|
+
FROM semicolony.cron_read_action_failure_alert_outbox AS current_alert
|
|
289
|
+
WHERE current_alert.state = 'pending'
|
|
290
|
+
ORDER BY current_alert.created_at, current_alert.occurrence_key
|
|
291
|
+
LIMIT 1
|
|
292
|
+
FOR UPDATE SKIP LOCKED;
|
|
293
|
+
|
|
294
|
+
IF NOT FOUND THEN
|
|
295
|
+
RETURN;
|
|
296
|
+
END IF;
|
|
297
|
+
|
|
298
|
+
UPDATE semicolony.cron_read_action_failure_alert_outbox AS current_alert
|
|
299
|
+
SET state = 'claimed',
|
|
300
|
+
claim_id = p_claim_id,
|
|
301
|
+
claimed_at = db_now,
|
|
302
|
+
claim_expires_at = db_now + pg_catalog.make_interval(secs => p_lease_seconds),
|
|
303
|
+
updated_at = db_now
|
|
304
|
+
WHERE current_alert.occurrence_key = alert.occurrence_key;
|
|
305
|
+
|
|
306
|
+
RETURN QUERY SELECT
|
|
307
|
+
'claimed'::text,
|
|
308
|
+
alert.occurrence_key,
|
|
309
|
+
alert.failure_code,
|
|
310
|
+
p_claim_id,
|
|
311
|
+
db_now,
|
|
312
|
+
db_now + pg_catalog.make_interval(secs => p_lease_seconds),
|
|
313
|
+
NULL::timestamptz;
|
|
314
|
+
END;
|
|
315
|
+
$$;
|
|
316
|
+
|
|
317
|
+
CREATE FUNCTION semicolony.hive_cron_complete_failure_alert(
|
|
318
|
+
p_occurrence_key text,
|
|
319
|
+
p_claim_id text,
|
|
320
|
+
p_outcome text
|
|
321
|
+
)
|
|
322
|
+
RETURNS TABLE (outcome text)
|
|
323
|
+
LANGUAGE plpgsql
|
|
324
|
+
SECURITY DEFINER
|
|
325
|
+
SET search_path = pg_catalog
|
|
326
|
+
SET TimeZone = 'UTC'
|
|
327
|
+
AS $$
|
|
328
|
+
DECLARE
|
|
329
|
+
alert record;
|
|
330
|
+
db_now timestamptz;
|
|
331
|
+
BEGIN
|
|
332
|
+
IF session_user <> 'sc_provider'
|
|
333
|
+
OR public.is_provider() IS DISTINCT FROM true THEN
|
|
334
|
+
RAISE EXCEPTION 'provider_mode_required' USING ERRCODE = '42501';
|
|
335
|
+
END IF;
|
|
336
|
+
|
|
337
|
+
IF p_occurrence_key IS NULL
|
|
338
|
+
OR (p_occurrence_key COLLATE "C") !~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,255}$'
|
|
339
|
+
OR p_claim_id IS NULL
|
|
340
|
+
OR (p_claim_id COLLATE "C") !~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
|
|
341
|
+
OR p_outcome IS NULL
|
|
342
|
+
OR p_outcome NOT IN ('sent', 'failed', 'ambiguous') THEN
|
|
343
|
+
RAISE EXCEPTION 'invalid_failure_alert_completion' USING ERRCODE = '22023';
|
|
344
|
+
END IF;
|
|
345
|
+
|
|
346
|
+
db_now := pg_catalog.clock_timestamp();
|
|
347
|
+
|
|
348
|
+
SELECT current_alert.state,
|
|
349
|
+
current_alert.claim_id
|
|
350
|
+
INTO alert
|
|
351
|
+
FROM semicolony.cron_read_action_failure_alert_outbox AS current_alert
|
|
352
|
+
WHERE current_alert.occurrence_key = p_occurrence_key
|
|
353
|
+
FOR UPDATE;
|
|
354
|
+
|
|
355
|
+
IF NOT FOUND THEN
|
|
356
|
+
outcome := 'not_found';
|
|
357
|
+
RETURN NEXT;
|
|
358
|
+
RETURN;
|
|
359
|
+
END IF;
|
|
360
|
+
|
|
361
|
+
IF alert.claim_id IS DISTINCT FROM p_claim_id THEN
|
|
362
|
+
outcome := 'claim_mismatch';
|
|
363
|
+
RETURN NEXT;
|
|
364
|
+
RETURN;
|
|
365
|
+
END IF;
|
|
366
|
+
|
|
367
|
+
IF alert.state IN ('sent', 'failed', 'ambiguous') THEN
|
|
368
|
+
outcome := CASE WHEN alert.state = p_outcome THEN 'existing' ELSE 'outcome_mismatch' END;
|
|
369
|
+
RETURN NEXT;
|
|
370
|
+
RETURN;
|
|
371
|
+
END IF;
|
|
372
|
+
|
|
373
|
+
IF alert.state <> 'claimed' THEN
|
|
374
|
+
outcome := 'claim_mismatch';
|
|
375
|
+
RETURN NEXT;
|
|
376
|
+
RETURN;
|
|
377
|
+
END IF;
|
|
378
|
+
|
|
379
|
+
UPDATE semicolony.cron_read_action_failure_alert_outbox AS current_alert
|
|
380
|
+
SET state = p_outcome,
|
|
381
|
+
resolved_at = db_now,
|
|
382
|
+
updated_at = db_now
|
|
383
|
+
WHERE current_alert.occurrence_key = p_occurrence_key;
|
|
384
|
+
|
|
385
|
+
outcome := 'completed';
|
|
386
|
+
RETURN NEXT;
|
|
387
|
+
END;
|
|
388
|
+
$$;
|
|
389
|
+
|
|
390
|
+
REVOKE ALL PRIVILEGES ON TABLE
|
|
391
|
+
semicolony.cron_read_action_failure_alert_outbox
|
|
392
|
+
FROM PUBLIC, sc_app, sc_provider;
|
|
393
|
+
|
|
394
|
+
REVOKE ALL ON FUNCTION semicolony.hive_cron_protect_failure_alert()
|
|
395
|
+
FROM PUBLIC, sc_app, sc_provider;
|
|
396
|
+
REVOKE ALL ON FUNCTION semicolony.hive_cron_record_failure_alert()
|
|
397
|
+
FROM PUBLIC, sc_app, sc_provider;
|
|
398
|
+
REVOKE ALL ON FUNCTION semicolony.hive_cron_claim_failure_alert(text, integer)
|
|
399
|
+
FROM PUBLIC, sc_app, sc_provider;
|
|
400
|
+
REVOKE ALL ON FUNCTION semicolony.hive_cron_complete_failure_alert(text, text, text)
|
|
401
|
+
FROM PUBLIC, sc_app, sc_provider;
|
|
402
|
+
|
|
403
|
+
GRANT EXECUTE ON FUNCTION semicolony.hive_cron_claim_failure_alert(text, integer)
|
|
404
|
+
TO sc_provider;
|
|
405
|
+
GRANT EXECUTE ON FUNCTION semicolony.hive_cron_complete_failure_alert(text, text, text)
|
|
406
|
+
TO sc_provider;
|