@nodii/saga 0.6.0 → 0.7.0

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/types.d.ts CHANGED
@@ -30,6 +30,12 @@ export interface SagaStateRow {
30
30
  failure_reason: string | null;
31
31
  failure_step: string | null;
32
32
  compensation_log: CompensationLogEntry[];
33
+ /** Durable compensation/undo stack (§ 5.8 recovery). Persisted in
34
+ * completed-step order so a fresh process can reload the pending
35
+ * compensations and run them in reverse on recovery. Empty when the
36
+ * saga has no completed compensable steps, or after a successful
37
+ * completion / compensation walk clears it. */
38
+ undo_stack: UndoStackEntry[];
33
39
  last_admin_action: string | null;
34
40
  last_admin_actor_id: string | null;
35
41
  last_admin_at: string | null;
@@ -42,6 +48,26 @@ export interface CompensationLogEntry {
42
48
  error?: string;
43
49
  ts: string;
44
50
  }
51
+ /**
52
+ * Durable undo-stack entry persisted on `saga_state.undo_stack`.
53
+ *
54
+ * The compensation/undo stack was process-local (an in-memory `Map`) until
55
+ * this entry was added — a process restart mid-saga LOST the list of
56
+ * completed steps' compensations, so a recovering process could not roll
57
+ * the saga back. The undo *function* itself cannot be serialized, so the
58
+ * durable record carries the step's IDENTITY (`step_name`), its `output`
59
+ * (the argument the undo fn receives), the compensation `mode`, and
60
+ * `has_undo` (false for steps registered with no undo — they log
61
+ * `skipped_no_undo`). On recovery, a fresh process re-binds the undo fn
62
+ * from the registered saga handler keyed by `step_name`.
63
+ */
64
+ export interface UndoStackEntry {
65
+ step_name: string;
66
+ output: unknown;
67
+ mode: "strict" | "best-effort";
68
+ /** false → the step had no undo (no-op compensation; logs skipped_no_undo). */
69
+ has_undo: boolean;
70
+ }
45
71
  /** § 5.4 — saga owns inputs only; @nodii/idempotency computes the key. */
46
72
  export interface IdempotencyShim {
47
73
  /**
@@ -76,6 +102,16 @@ export interface SagaStateStore {
76
102
  updateSagaStatus(sagaId: string, update: Partial<Pick<SagaStateRow, "status" | "current_step" | "completed_at" | "failure_reason" | "failure_step" | "last_admin_action" | "last_admin_actor_id" | "last_admin_at" | "cancel_reason" | "next_resume_at" | "reaper_grace_ms">>): Promise<void>;
77
103
  appendStepOutput(sagaId: string, stepName: string, output: unknown): Promise<void>;
78
104
  appendCompensationLog(sagaId: string, entry: CompensationLogEntry): Promise<void>;
105
+ /** Durably append one undo-stack entry to `saga_state.undo_stack` (§ 5.8
106
+ * recovery). Called by `step()` after a compensable step succeeds, so
107
+ * the pending-compensation list survives a process restart. Append-only
108
+ * + ordered (completed-step order) — the recovery + compensation walk
109
+ * reverse it. Production-bound stores (Postgres) persist to the jsonb
110
+ * column; the in-memory double mirrors it in the row. */
111
+ appendUndoEntry(sagaId: string, entry: UndoStackEntry): Promise<void>;
112
+ /** Clear `saga_state.undo_stack` once compensation has fully run (or the
113
+ * saga completed and no rollback is possible/needed). Idempotent. */
114
+ clearUndoStack(sagaId: string): Promise<void>;
79
115
  /** Optional enumeration — production-bound stores (Postgres) MUST
80
116
  * implement this; tests can omit. Returns a defensive snapshot. */
81
117
  list?(filter?: ListSagasFilter): Promise<SagaStateRow[]>;
@@ -228,10 +264,50 @@ export interface SagaInterceptorCall {
228
264
  };
229
265
  request: unknown;
230
266
  }
267
+ /**
268
+ * Authorization context handed to the {@link SagaAdminAuthorizer} for every
269
+ * admin RPC. `actorPermissions` is the caller's effective permission set —
270
+ * the consuming service resolves it from the verified actor envelope
271
+ * (`@nodii/grpc-auth` `checkUserPermission` / `NodiiClaims.permissions`)
272
+ * and passes it on the request. The authorizer decides whether the actor
273
+ * holds `requiredPermission` (one of the locked {@link SAGA_ADMIN_PERMISSIONS}).
274
+ */
275
+ export interface SagaAdminAuthContext {
276
+ /** The locked permission the RPC requires (a `SAGA_ADMIN_PERMISSIONS` value). */
277
+ requiredPermission: SagaAdminPermission;
278
+ /** The gRPC-style method name being authorized (e.g. "RetryStep"). */
279
+ method: string;
280
+ /** Saga the op targets (for tenant-scoped or row-scoped authorizers). */
281
+ sagaId: string;
282
+ /** The caller's effective permission set, resolved upstream from the
283
+ * verified actor envelope. Empty/absent ⇒ unauthorized. */
284
+ actorPermissions: readonly string[];
285
+ /** Opaque actor id (audit + row-scoped checks); optional. */
286
+ actorId?: string;
287
+ }
288
+ /**
289
+ * Pluggable admin authorizer (§ 5.10). Returns `true` to allow, `false` (or
290
+ * throws) to reject. The DEFAULT authorizer (when none is supplied) is a
291
+ * pure permission-set membership check against the locked
292
+ * {@link SAGA_ADMIN_PERMISSIONS} — i.e. `ctx.actorPermissions.includes(
293
+ * ctx.requiredPermission)`. Services that need tenant/row scoping or a
294
+ * remote RBAC resolver supply their own. There is NO "allow-all" default
295
+ * (R1): an op with no matching permission in `actorPermissions` is rejected
296
+ * with {@link SagaAdminUnauthorized}.
297
+ */
298
+ export type SagaAdminAuthorizer = (ctx: SagaAdminAuthContext) => boolean | Promise<boolean>;
231
299
  /** SagaAdminService factory opts. */
232
300
  export interface SagaAdminServiceOpts {
233
301
  stateStore: SagaStateStore;
234
302
  audit?: TelemetryAuditEmitter;
303
+ /**
304
+ * Admin authorizer (§ 5.10). When omitted, the built-in
305
+ * permission-membership authorizer is used: each write/read RPC is gated
306
+ * on its locked {@link SAGA_ADMIN_PERMISSIONS} value, checked against the
307
+ * `actorPermissions` carried on the request. Supply a custom authorizer
308
+ * for tenant/row-scoped checks or a remote RBAC resolver.
309
+ */
310
+ authorizer?: SagaAdminAuthorizer;
235
311
  }
236
312
  /** § 5.10 — minimum justification length per D164. */
237
313
  export declare const MIN_JUSTIFICATION_CHARS = 20;
@@ -281,6 +357,25 @@ export declare class SagaCompensationFailed extends SagaError {
281
357
  export declare class JustificationRequired extends SagaError {
282
358
  constructor(actual: number);
283
359
  }
360
+ /**
361
+ * Raised by every `SagaAdminServer` RPC when the caller does not hold the
362
+ * locked admin permission the op requires (one of {@link SAGA_ADMIN_PERMISSIONS}).
363
+ *
364
+ * Administrative saga operations (force-complete / cancel / retry / skip /
365
+ * force-compensate / manual-resolve, and the read RPCs) MUST be gated on an
366
+ * admin authorization — before this error existed, any caller could drive
367
+ * them with only a `justification` string. The rejection path still emits
368
+ * the `*_unauthorized` audit row so the denied attempt is traceable.
369
+ *
370
+ * gRPC mapping: PERMISSION_DENIED (code 7).
371
+ */
372
+ export declare class SagaAdminUnauthorized extends SagaError {
373
+ /** The locked permission the rejected op required. */
374
+ readonly requiredPermission: SagaAdminPermission;
375
+ /** The RPC method that was rejected. */
376
+ readonly method: string;
377
+ constructor(method: string, requiredPermission: SagaAdminPermission);
378
+ }
284
379
  export declare class SagaTypeNotRegistered extends SagaError {
285
380
  readonly sagaType: string;
286
381
  constructor(sagaType: string);
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js CHANGED
@@ -103,6 +103,30 @@ export class JustificationRequired extends SagaError {
103
103
  this.name = "JustificationRequired";
104
104
  }
105
105
  }
106
+ /**
107
+ * Raised by every `SagaAdminServer` RPC when the caller does not hold the
108
+ * locked admin permission the op requires (one of {@link SAGA_ADMIN_PERMISSIONS}).
109
+ *
110
+ * Administrative saga operations (force-complete / cancel / retry / skip /
111
+ * force-compensate / manual-resolve, and the read RPCs) MUST be gated on an
112
+ * admin authorization — before this error existed, any caller could drive
113
+ * them with only a `justification` string. The rejection path still emits
114
+ * the `*_unauthorized` audit row so the denied attempt is traceable.
115
+ *
116
+ * gRPC mapping: PERMISSION_DENIED (code 7).
117
+ */
118
+ export class SagaAdminUnauthorized extends SagaError {
119
+ /** The locked permission the rejected op required. */
120
+ requiredPermission;
121
+ /** The RPC method that was rejected. */
122
+ method;
123
+ constructor(method, requiredPermission) {
124
+ super(`saga_admin_unauthorized: ${method} requires the '${requiredPermission}' permission; caller is not authorized.`);
125
+ this.name = "SagaAdminUnauthorized";
126
+ this.method = method;
127
+ this.requiredPermission = requiredPermission;
128
+ }
129
+ }
106
130
  export class SagaTypeNotRegistered extends SagaError {
107
131
  sagaType;
108
132
  constructor(sagaType) {
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nodii/saga",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Saga orchestration library for the Nodii microservice stack — createSaga + step + stepParallel + cross-saga signals + sagaContext interceptor + SagaAdminService factory + @sagaCallable discipline tag + real PostgresSagaStateStore + RedisSignalBus + Pattern 2 async-step + reaper. Polyglot per D159 (TS + Python + Go).",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -44,8 +44,9 @@
44
44
  }
45
45
  },
46
46
  "devDependencies": {
47
- "@nodii/grpc-auth": "0.5.1",
48
- "@nodii/telemetry": "0.5.2",
47
+ "@nodii/db-rls": "0.7.2",
48
+ "@nodii/grpc-auth": "0.9.1",
49
+ "@nodii/telemetry": "0.9.0",
49
50
  "@types/bun": "^1.3.13",
50
51
  "ioredis": "^5.4.0",
51
52
  "postgres": "^3.4.0",
@@ -4,13 +4,21 @@
4
4
  -- 5.5 lists it under "lifecycle" alongside completed_at). Plus a small
5
5
  -- saga_outbox for Pattern 2 begin/completion events.
6
6
  --
7
- -- This file is the canonical source for the per-service migration; the
8
- -- `migrate-gen` helper (`src/migrate-gen.ts`) copies the contents into a
9
- -- service's migrations folder verbatim.
7
+ -- This file is the downstream-facing copy of the saga migration for services
8
+ -- that run their own migration tool (Flyway / sqlx-cli / golang-migrate /
9
+ -- alembic). The runtime source of truth is the inlined SAGA_STATE_MIGRATION_SQL
10
+ -- constant in `src/migrations/index.ts` (applied by `applySagaMigrations`); this
11
+ -- .sql must stay in lockstep with it. A drift-guard test in
12
+ -- `tests/rls.integration.test.ts` asserts the two produce an identical statement
13
+ -- sequence (via `splitStatements`), so an edit to one that misses the other
14
+ -- fails CI.
10
15
 
11
16
  CREATE TABLE IF NOT EXISTS saga_state (
12
17
  id TEXT PRIMARY KEY,
13
- tenant_id TEXT,
18
+ -- D412 / 08-rls v7 (A1): tenant_id is UUID NOT NULL. Fresh installs get the
19
+ -- UUID type directly; pre-D412 installs (tenant_id TEXT) are migrated in
20
+ -- place by the guarded ALTER block below.
21
+ tenant_id UUID NOT NULL,
14
22
  type TEXT NOT NULL,
15
23
  status TEXT NOT NULL,
16
24
  current_step TEXT,
@@ -39,6 +47,11 @@ CREATE TABLE IF NOT EXISTS saga_state (
39
47
 
40
48
  -- Compensation
41
49
  compensation_log JSONB NOT NULL DEFAULT '[]'::jsonb,
50
+ -- Durable undo/compensation stack (§ 5.8 recovery). Pending-compensation
51
+ -- list persisted in completed-step order so a fresh process can reload it
52
+ -- after a restart and run the undos in reverse. Was process-local (in-
53
+ -- memory) before this column existed → a crash mid-saga lost the rollback.
54
+ undo_stack JSONB NOT NULL DEFAULT '[]'::jsonb,
42
55
 
43
56
  -- Admin recovery (D164)
44
57
  last_admin_action TEXT,
@@ -53,6 +66,30 @@ CREATE TABLE IF NOT EXISTS saga_state (
53
66
  -- Idempotent add for services that bootstrapped saga_state before the
54
67
  -- per-step grace column existed (request 5092d0ba / drift e5e813d0).
55
68
  ALTER TABLE saga_state ADD COLUMN IF NOT EXISTS reaper_grace_ms BIGINT;
69
+ -- Idempotent add for services that bootstrapped saga_state before the
70
+ -- durable undo stack existed (saga admin-authz + undo-durability wave).
71
+ ALTER TABLE saga_state ADD COLUMN IF NOT EXISTS undo_stack JSONB NOT NULL DEFAULT '[]'::jsonb;
72
+
73
+ -- D412 / 08-rls v7 (A1) — idempotent in-place migration of pre-D412 installs
74
+ -- whose tenant_id is still TEXT. Guarded so re-runs (and fresh UUID installs)
75
+ -- are a no-op: only ALTER when the column's current type is not already uuid.
76
+ -- `USING tenant_id::uuid` fails loudly on non-UUID rows — under A1 those are
77
+ -- malformed tenant identifiers that must be fixed, not silently coerced.
78
+ DO $$
79
+ BEGIN
80
+ IF EXISTS (
81
+ SELECT 1 FROM information_schema.columns
82
+ WHERE table_schema = current_schema()
83
+ AND table_name = 'saga_state'
84
+ AND column_name = 'tenant_id'
85
+ AND data_type <> 'uuid'
86
+ ) THEN
87
+ EXECUTE 'ALTER TABLE saga_state ALTER COLUMN tenant_id TYPE uuid USING tenant_id::uuid';
88
+ END IF;
89
+ END
90
+ $$;
91
+ -- Enforce NOT NULL (A1: every tenant-scoped row carries a tenant). Idempotent.
92
+ ALTER TABLE saga_state ALTER COLUMN tenant_id SET NOT NULL;
56
93
 
57
94
  -- Spec § 5.5 — four indexes.
58
95
  CREATE UNIQUE INDEX IF NOT EXISTS saga_state_trigger_trace_id_uniq
@@ -76,7 +113,11 @@ CREATE TABLE IF NOT EXISTS saga_outbox (
76
113
  step_name TEXT NOT NULL,
77
114
  event_type TEXT NOT NULL,
78
115
  payload JSONB NOT NULL,
79
- tenant_id TEXT,
116
+ -- D412 / 08-rls v7 (A1): tenant_id is UUID so the canonical UUID-typed A1
117
+ -- policies below can bind. NULLABLE by design (unlike saga_state): the
118
+ -- participant-worker writes a NULL tenant for tenant-less sagas, and a NULL
119
+ -- tenant row is owner-only (invisible to non-owner roles) under the policies.
120
+ tenant_id UUID,
80
121
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
81
122
  delivered_at TIMESTAMPTZ
82
123
  );
@@ -84,3 +125,96 @@ CREATE TABLE IF NOT EXISTS saga_outbox (
84
125
  CREATE INDEX IF NOT EXISTS saga_outbox_saga_idx ON saga_outbox (saga_id, created_at);
85
126
  CREATE INDEX IF NOT EXISTS saga_outbox_undelivered_idx ON saga_outbox (delivered_at)
86
127
  WHERE delivered_at IS NULL;
128
+
129
+ -- D412 / 08-rls v7 (A1) — idempotent in-place migration of pre-D412 installs
130
+ -- whose saga_outbox.tenant_id is still TEXT. Guarded so re-runs (and fresh UUID
131
+ -- installs) are a no-op. Both the type change AND the one-time backfill of any
132
+ -- legacy NULL tenant (from the parent saga_state row) live INSIDE the guard, so
133
+ -- the backfill runs only during the actual upgrade — not as an unbounded scan on
134
+ -- every boot. The backfill runs after the type change (both columns uuid) via a
135
+ -- dynamic EXECUTE so it is planned against the just-altered column; orphaned rows
136
+ -- whose saga is gone simply stay NULL (owner-only under RLS).
137
+ DO $$
138
+ BEGIN
139
+ IF EXISTS (
140
+ SELECT 1 FROM information_schema.columns
141
+ WHERE table_schema = current_schema()
142
+ AND table_name = 'saga_outbox'
143
+ AND column_name = 'tenant_id'
144
+ AND data_type <> 'uuid'
145
+ ) THEN
146
+ EXECUTE 'ALTER TABLE saga_outbox ALTER COLUMN tenant_id TYPE uuid USING tenant_id::uuid';
147
+ EXECUTE 'UPDATE saga_outbox o SET tenant_id = s.tenant_id FROM saga_state s WHERE o.saga_id = s.id AND o.tenant_id IS NULL';
148
+ END IF;
149
+ END
150
+ $$;
151
+
152
+ -- D412 / 08-rls v7 (A1) — canonical 5-policy* RLS on saga_state. The CREATE
153
+ -- POLICY statements below are byte-equal to
154
+ -- withRls('saga_state', { allow: ['SELECT','INSERT','UPDATE','DELETE'] })
155
+ -- from @nodii/db-rls. generateSagaStateRlsDdl() in migrations/index.ts INLINES
156
+ -- that same block as a string constant (NO runtime db-rls call → the published
157
+ -- @nodii/saga has no runtime db-rls dependency); a byte-equality test asserts
158
+ -- the inlined const stays equal to db-rls's live generator output, so this file
159
+ -- and the inlined const stay in lockstep. *full-CRUD allow → 1 owner
160
+ -- + 4 authenticated + 4 services = 9 policies; "5-policy" is the doctrine's
161
+ -- floor name for the per-role/per-verb family.
162
+ --
163
+ -- CREATE POLICY has no IF NOT EXISTS, so each is preceded by DROP POLICY
164
+ -- IF EXISTS to keep the migration idempotent. ENABLE ROW LEVEL SECURITY and
165
+ -- the GRANTs are already idempotent.
166
+ --
167
+ -- Adopters bind the app.tenant_id GUC (via auth.set_tenant_id / the db-rls
168
+ -- withSystemContext dispatch) on the nodii_services pool; this lib only
169
+ -- emits the DDL (08-rls § 7).
170
+ ALTER TABLE saga_state ENABLE ROW LEVEL SECURITY;
171
+ GRANT SELECT, INSERT, UPDATE, DELETE ON saga_state TO nodii_services;
172
+ GRANT SELECT, INSERT, UPDATE, DELETE ON saga_state TO authenticated;
173
+ DROP POLICY IF EXISTS saga_state_owner_policy ON saga_state;
174
+ CREATE POLICY saga_state_owner_policy ON saga_state FOR ALL TO nodii_owner USING (true) WITH CHECK (true);
175
+ DROP POLICY IF EXISTS saga_state_auth_select_policy ON saga_state;
176
+ CREATE POLICY saga_state_auth_select_policy ON saga_state FOR SELECT TO authenticated USING (tenant_id IN (SELECT auth.user_tenant_ids(auth.get_user_id())));
177
+ DROP POLICY IF EXISTS saga_state_auth_insert_policy ON saga_state;
178
+ CREATE POLICY saga_state_auth_insert_policy ON saga_state FOR INSERT TO authenticated WITH CHECK (tenant_id IN (SELECT auth.user_tenant_ids(auth.get_user_id())));
179
+ DROP POLICY IF EXISTS saga_state_auth_update_policy ON saga_state;
180
+ CREATE POLICY saga_state_auth_update_policy ON saga_state FOR UPDATE TO authenticated USING (tenant_id IN (SELECT auth.user_tenant_ids(auth.get_user_id()))) WITH CHECK (tenant_id IN (SELECT auth.user_tenant_ids(auth.get_user_id())));
181
+ DROP POLICY IF EXISTS saga_state_auth_delete_policy ON saga_state;
182
+ CREATE POLICY saga_state_auth_delete_policy ON saga_state FOR DELETE TO authenticated USING (tenant_id IN (SELECT auth.user_tenant_ids(auth.get_user_id())));
183
+ DROP POLICY IF EXISTS saga_state_svc_select_policy ON saga_state;
184
+ CREATE POLICY saga_state_svc_select_policy ON saga_state FOR SELECT TO nodii_services USING (tenant_id = auth.get_tenant_id());
185
+ DROP POLICY IF EXISTS saga_state_svc_insert_policy ON saga_state;
186
+ CREATE POLICY saga_state_svc_insert_policy ON saga_state FOR INSERT TO nodii_services WITH CHECK (tenant_id = auth.get_tenant_id());
187
+ DROP POLICY IF EXISTS saga_state_svc_update_policy ON saga_state;
188
+ CREATE POLICY saga_state_svc_update_policy ON saga_state FOR UPDATE TO nodii_services USING (tenant_id = auth.get_tenant_id()) WITH CHECK (tenant_id = auth.get_tenant_id());
189
+ DROP POLICY IF EXISTS saga_state_svc_delete_policy ON saga_state;
190
+ CREATE POLICY saga_state_svc_delete_policy ON saga_state FOR DELETE TO nodii_services USING (tenant_id = auth.get_tenant_id());
191
+
192
+ -- D412 / 08-rls v7 (A1) — canonical 5-policy* RLS on saga_outbox (every table
193
+ -- with a tenant_id column, no exceptions). saga_outbox is tenant-scoped (each
194
+ -- row carries the saga's tenant_id) and readOutboxForSaga filters by saga_id
195
+ -- ONLY, so RLS is the sole tenant-isolation boundary. Byte-equal to
196
+ -- withRls('saga_outbox', { allow: ['SELECT','INSERT','UPDATE','DELETE'] })
197
+ -- from @nodii/db-rls; generateSagaOutboxRlsDdl() in migrations/index.ts inlines
198
+ -- the same block (no runtime db-rls dep), byte-equality-asserted in
199
+ -- tests/rls.integration.test.ts. *1 owner + 4 authenticated + 4 services = 9.
200
+ ALTER TABLE saga_outbox ENABLE ROW LEVEL SECURITY;
201
+ GRANT SELECT, INSERT, UPDATE, DELETE ON saga_outbox TO nodii_services;
202
+ GRANT SELECT, INSERT, UPDATE, DELETE ON saga_outbox TO authenticated;
203
+ DROP POLICY IF EXISTS saga_outbox_owner_policy ON saga_outbox;
204
+ CREATE POLICY saga_outbox_owner_policy ON saga_outbox FOR ALL TO nodii_owner USING (true) WITH CHECK (true);
205
+ DROP POLICY IF EXISTS saga_outbox_auth_select_policy ON saga_outbox;
206
+ CREATE POLICY saga_outbox_auth_select_policy ON saga_outbox FOR SELECT TO authenticated USING (tenant_id IN (SELECT auth.user_tenant_ids(auth.get_user_id())));
207
+ DROP POLICY IF EXISTS saga_outbox_auth_insert_policy ON saga_outbox;
208
+ CREATE POLICY saga_outbox_auth_insert_policy ON saga_outbox FOR INSERT TO authenticated WITH CHECK (tenant_id IN (SELECT auth.user_tenant_ids(auth.get_user_id())));
209
+ DROP POLICY IF EXISTS saga_outbox_auth_update_policy ON saga_outbox;
210
+ CREATE POLICY saga_outbox_auth_update_policy ON saga_outbox FOR UPDATE TO authenticated USING (tenant_id IN (SELECT auth.user_tenant_ids(auth.get_user_id()))) WITH CHECK (tenant_id IN (SELECT auth.user_tenant_ids(auth.get_user_id())));
211
+ DROP POLICY IF EXISTS saga_outbox_auth_delete_policy ON saga_outbox;
212
+ CREATE POLICY saga_outbox_auth_delete_policy ON saga_outbox FOR DELETE TO authenticated USING (tenant_id IN (SELECT auth.user_tenant_ids(auth.get_user_id())));
213
+ DROP POLICY IF EXISTS saga_outbox_svc_select_policy ON saga_outbox;
214
+ CREATE POLICY saga_outbox_svc_select_policy ON saga_outbox FOR SELECT TO nodii_services USING (tenant_id = auth.get_tenant_id());
215
+ DROP POLICY IF EXISTS saga_outbox_svc_insert_policy ON saga_outbox;
216
+ CREATE POLICY saga_outbox_svc_insert_policy ON saga_outbox FOR INSERT TO nodii_services WITH CHECK (tenant_id = auth.get_tenant_id());
217
+ DROP POLICY IF EXISTS saga_outbox_svc_update_policy ON saga_outbox;
218
+ CREATE POLICY saga_outbox_svc_update_policy ON saga_outbox FOR UPDATE TO nodii_services USING (tenant_id = auth.get_tenant_id()) WITH CHECK (tenant_id = auth.get_tenant_id());
219
+ DROP POLICY IF EXISTS saga_outbox_svc_delete_policy ON saga_outbox;
220
+ CREATE POLICY saga_outbox_svc_delete_policy ON saga_outbox FOR DELETE TO nodii_services USING (tenant_id = auth.get_tenant_id());