@sequenceholdings/pipeline-spec 0.1.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/README.md +114 -0
- package/dist/authoring/per-table-ingestion.d.ts +74 -0
- package/dist/authoring/per-table-ingestion.d.ts.map +1 -0
- package/dist/authoring/per-table-ingestion.js +122 -0
- package/dist/authoring/per-table-ingestion.js.map +1 -0
- package/dist/authoring/yaml.d.ts +6 -0
- package/dist/authoring/yaml.d.ts.map +1 -0
- package/dist/authoring/yaml.js +15 -0
- package/dist/authoring/yaml.js.map +1 -0
- package/dist/binding-gaps.d.ts +21 -0
- package/dist/binding-gaps.d.ts.map +1 -0
- package/dist/binding-gaps.js +74 -0
- package/dist/binding-gaps.js.map +1 -0
- package/dist/bodies/ingestion.d.ts +359 -0
- package/dist/bodies/ingestion.d.ts.map +1 -0
- package/dist/bodies/ingestion.js +446 -0
- package/dist/bodies/ingestion.js.map +1 -0
- package/dist/bodies/serving.d.ts +316 -0
- package/dist/bodies/serving.d.ts.map +1 -0
- package/dist/bodies/serving.js +290 -0
- package/dist/bodies/serving.js.map +1 -0
- package/dist/bodies/transformation.d.ts +397 -0
- package/dist/bodies/transformation.d.ts.map +1 -0
- package/dist/bodies/transformation.js +278 -0
- package/dist/bodies/transformation.js.map +1 -0
- package/dist/catalog-binding.d.ts +15 -0
- package/dist/catalog-binding.d.ts.map +1 -0
- package/dist/catalog-binding.js +15 -0
- package/dist/catalog-binding.js.map +1 -0
- package/dist/columns.d.ts +177 -0
- package/dist/columns.d.ts.map +1 -0
- package/dist/columns.js +89 -0
- package/dist/columns.js.map +1 -0
- package/dist/compatibility.d.ts +25 -0
- package/dist/compatibility.d.ts.map +1 -0
- package/dist/compatibility.js +108 -0
- package/dist/compatibility.js.map +1 -0
- package/dist/constants.d.ts +95 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +105 -0
- package/dist/constants.js.map +1 -0
- package/dist/diff.d.ts +36 -0
- package/dist/diff.d.ts.map +1 -0
- package/dist/diff.js +300 -0
- package/dist/diff.js.map +1 -0
- package/dist/documentation.d.ts +22 -0
- package/dist/documentation.d.ts.map +1 -0
- package/dist/documentation.js +43 -0
- package/dist/documentation.js.map +1 -0
- package/dist/envelope.d.ts +1241 -0
- package/dist/envelope.d.ts.map +1 -0
- package/dist/envelope.js +163 -0
- package/dist/envelope.js.map +1 -0
- package/dist/errors.d.ts +30 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +47 -0
- package/dist/errors.js.map +1 -0
- package/dist/graph-references.d.ts +34 -0
- package/dist/graph-references.d.ts.map +1 -0
- package/dist/graph-references.js +81 -0
- package/dist/graph-references.js.map +1 -0
- package/dist/graph.d.ts +112 -0
- package/dist/graph.d.ts.map +1 -0
- package/dist/graph.js +546 -0
- package/dist/graph.js.map +1 -0
- package/dist/hash.d.ts +28 -0
- package/dist/hash.d.ts.map +1 -0
- package/dist/hash.js +91 -0
- package/dist/hash.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/issues.d.ts +14 -0
- package/dist/issues.d.ts.map +1 -0
- package/dist/issues.js +27 -0
- package/dist/issues.js.map +1 -0
- package/dist/loader.d.ts +50 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +241 -0
- package/dist/loader.js.map +1 -0
- package/dist/migrations/contracts.d.ts +38 -0
- package/dist/migrations/contracts.d.ts.map +1 -0
- package/dist/migrations/contracts.js +175 -0
- package/dist/migrations/contracts.js.map +1 -0
- package/dist/migrations/manifest.d.ts +137 -0
- package/dist/migrations/manifest.d.ts.map +1 -0
- package/dist/migrations/manifest.js +137 -0
- package/dist/migrations/manifest.js.map +1 -0
- package/dist/operations.d.ts +214 -0
- package/dist/operations.d.ts.map +1 -0
- package/dist/operations.js +275 -0
- package/dist/operations.js.map +1 -0
- package/dist/orm-satisfies.d.ts +132 -0
- package/dist/orm-satisfies.d.ts.map +1 -0
- package/dist/orm-satisfies.js +119 -0
- package/dist/orm-satisfies.js.map +1 -0
- package/dist/primitives.d.ts +11 -0
- package/dist/primitives.d.ts.map +1 -0
- package/dist/primitives.js +20 -0
- package/dist/primitives.js.map +1 -0
- package/dist/resolve.d.ts +124 -0
- package/dist/resolve.d.ts.map +1 -0
- package/dist/resolve.js +194 -0
- package/dist/resolve.js.map +1 -0
- package/dist/secret-scan.d.ts +34 -0
- package/dist/secret-scan.d.ts.map +1 -0
- package/dist/secret-scan.js +98 -0
- package/dist/secret-scan.js.map +1 -0
- package/dist/serving-compatibility.d.ts +14 -0
- package/dist/serving-compatibility.d.ts.map +1 -0
- package/dist/serving-compatibility.js +19 -0
- package/dist/serving-compatibility.js.map +1 -0
- package/dist/snapshot-transport.d.ts +83 -0
- package/dist/snapshot-transport.d.ts.map +1 -0
- package/dist/snapshot-transport.js +42 -0
- package/dist/snapshot-transport.js.map +1 -0
- package/dist/suggestions.d.ts +3 -0
- package/dist/suggestions.d.ts.map +1 -0
- package/dist/suggestions.js +26 -0
- package/dist/suggestions.js.map +1 -0
- package/dist/types.d.ts +72 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +119 -0
- package/dist/types.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { type ServingTransport } from '../snapshot-transport.js';
|
|
3
|
+
import { type CatalogBinding } from '../catalog-binding.js';
|
|
4
|
+
import { type ColumnMap, type ColumnsOrRef } from '../columns.js';
|
|
5
|
+
/**
|
|
6
|
+
* Serving stages replace the manual synced-table chain (synced-tables.yml →
|
|
7
|
+
* provision → UUID pinning → fan-out task → view DDL) with a declaration, and
|
|
8
|
+
* carry the ORM coupling surface: an explicit projection contract plus the
|
|
9
|
+
* `orm_binding` with the reserved `managed` mode.
|
|
10
|
+
*
|
|
11
|
+
* ## Naming-plane rules (three planes — per the adversarial ORM review)
|
|
12
|
+
*
|
|
13
|
+
* 1. **UC source name** (`gold.loans`) — the Unity Catalog relation the sync
|
|
14
|
+
* reads. Optional `source.catalog` overrides the deploy catalog for this
|
|
15
|
+
* plane only (e.g. `src_banksouth_fis.gold.loans`); the synced-table
|
|
16
|
+
* destination still lands in the deployment catalog. The ORM's `source:`
|
|
17
|
+
* field on synced tables refers to THIS plane and is display metadata —
|
|
18
|
+
* it is ambiguous against `synced_*` physical names and must never be
|
|
19
|
+
* string-matched for platform↔ORM joins.
|
|
20
|
+
* 2. **Postgres physical relation** — the Lakebase relation the sync engine
|
|
21
|
+
* creates. Captured at **provision time and stored in the registry**,
|
|
22
|
+
* never re-derived: the estate has documented derivation drift
|
|
23
|
+
* (`df_retail_customers`).
|
|
24
|
+
* 3. **Public view** (`expose.view`) — the stable consumer-facing name.
|
|
25
|
+
*
|
|
26
|
+
* `orm_binding` (namespace + table) is the **canonical join key** for all
|
|
27
|
+
* platform↔ORM checks.
|
|
28
|
+
*
|
|
29
|
+
* ## sync_mode validity (declared here, enforced at plan time)
|
|
30
|
+
*
|
|
31
|
+
* - A materialized-view source supports `SNAPSHOT` only (full refresh).
|
|
32
|
+
* - `CONTINUOUS` requires a change-data-feed-capable source table.
|
|
33
|
+
* These rules need live catalog facts, so the offline SDK documents them and
|
|
34
|
+
* the plan step (M7) enforces them; `validateSpecGraph` applies the offline
|
|
35
|
+
* subset (write-pattern sanity).
|
|
36
|
+
*/
|
|
37
|
+
export declare const SYNC_MODES: readonly ["SNAPSHOT", "TRIGGERED", "CONTINUOUS"];
|
|
38
|
+
export declare const syncModeSchema: z.ZodEnum<{
|
|
39
|
+
SNAPSHOT: "SNAPSHOT";
|
|
40
|
+
TRIGGERED: "TRIGGERED";
|
|
41
|
+
CONTINUOUS: "CONTINUOUS";
|
|
42
|
+
}>;
|
|
43
|
+
export type SyncMode = z.infer<typeof syncModeSchema>;
|
|
44
|
+
export declare const PUBLIC_VIEW_ACCESS: readonly ["standard", "reporting", "owner_only", "orm_only"];
|
|
45
|
+
export declare const publicViewAccessSchema: z.ZodEnum<{
|
|
46
|
+
standard: "standard";
|
|
47
|
+
reporting: "reporting";
|
|
48
|
+
owner_only: "owner_only";
|
|
49
|
+
orm_only: "orm_only";
|
|
50
|
+
}>;
|
|
51
|
+
export type PublicViewAccess = z.infer<typeof publicViewAccessSchema>;
|
|
52
|
+
/** The served contract: projected columns + the primary key of the synced relation. */
|
|
53
|
+
export declare const projectionSchema: z.ZodObject<{
|
|
54
|
+
columns: z.ZodUnion<readonly [z.ZodObject<{
|
|
55
|
+
schema_ref: z.ZodString;
|
|
56
|
+
}, z.core.$strict>, z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
57
|
+
type: z.ZodUnion<readonly [z.ZodEnum<{
|
|
58
|
+
string: "string";
|
|
59
|
+
boolean: "boolean";
|
|
60
|
+
uuid: "uuid";
|
|
61
|
+
int: "int";
|
|
62
|
+
long: "long";
|
|
63
|
+
numeric: "numeric";
|
|
64
|
+
double: "double";
|
|
65
|
+
timestamp: "timestamp";
|
|
66
|
+
date: "date";
|
|
67
|
+
json: "json";
|
|
68
|
+
}>, z.ZodEnum<{
|
|
69
|
+
float: "float";
|
|
70
|
+
timestamp_ntz: "timestamp_ntz";
|
|
71
|
+
array: "array";
|
|
72
|
+
map: "map";
|
|
73
|
+
struct: "struct";
|
|
74
|
+
binary: "binary";
|
|
75
|
+
}>, z.ZodString]>;
|
|
76
|
+
nullable: z.ZodDefault<z.ZodBoolean>;
|
|
77
|
+
key: z.ZodDefault<z.ZodBoolean>;
|
|
78
|
+
domain: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
|
|
79
|
+
description: z.ZodOptional<z.ZodString>;
|
|
80
|
+
on_violation: z.ZodDefault<z.ZodEnum<{
|
|
81
|
+
fail: "fail";
|
|
82
|
+
quarantine: "quarantine";
|
|
83
|
+
warn: "warn";
|
|
84
|
+
}>>;
|
|
85
|
+
}, z.core.$strict>>]>;
|
|
86
|
+
primary_key: z.ZodArray<z.ZodString>;
|
|
87
|
+
}, z.core.$strict>;
|
|
88
|
+
export type Projection = z.infer<typeof projectionSchema>;
|
|
89
|
+
/**
|
|
90
|
+
* Join key into the Sequence ORM: the serving stage's synced relation backs
|
|
91
|
+
* the ORM table `<namespace>.<table>`.
|
|
92
|
+
*
|
|
93
|
+
* `mode: referenced` — the ORM declares the table as a synced reflection
|
|
94
|
+
* (declaration-only; the ORM engine excludes it from DDL/grants/policies).
|
|
95
|
+
* `mode: managed` is RESERVED (ORM-owned lifecycle) and rejected until the
|
|
96
|
+
* ORM-coupling milestone ships.
|
|
97
|
+
*/
|
|
98
|
+
export declare const ormBindingSchema: z.ZodObject<{
|
|
99
|
+
namespace: z.ZodString;
|
|
100
|
+
table: z.ZodString;
|
|
101
|
+
mode: z.ZodEnum<{
|
|
102
|
+
referenced: "referenced";
|
|
103
|
+
managed: "managed";
|
|
104
|
+
}>;
|
|
105
|
+
}, z.core.$strict>;
|
|
106
|
+
export type OrmBinding = z.infer<typeof ormBindingSchema>;
|
|
107
|
+
/**
|
|
108
|
+
* ORM-first conformance: this projection promises to satisfy the published
|
|
109
|
+
* contract for `<namespace>.<table>` at `content_hash`. Compatibility is
|
|
110
|
+
* enforced offline by `validateSpecGraph` (when an ORM contract catalog is
|
|
111
|
+
* supplied) and at provision plan time — see `checkServingSatisfiesOrmContract`.
|
|
112
|
+
*
|
|
113
|
+
* `mode: managed` stays reserved on `orm_binding`; this binding is the
|
|
114
|
+
* hash-pinned contract reference only.
|
|
115
|
+
*/
|
|
116
|
+
export declare const satisfiesSchema: z.ZodObject<{
|
|
117
|
+
namespace: z.ZodString;
|
|
118
|
+
table: z.ZodString;
|
|
119
|
+
content_hash: z.ZodString;
|
|
120
|
+
}, z.core.$strict>;
|
|
121
|
+
export type SatisfiesBinding = z.infer<typeof satisfiesSchema>;
|
|
122
|
+
export declare const servingBodyShape: {
|
|
123
|
+
transport: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
124
|
+
kind: z.ZodLiteral<"native_lakebase_sync_v1">;
|
|
125
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
126
|
+
kind: z.ZodLiteral<"postgres_snapshot_landing_v1">;
|
|
127
|
+
binding: z.ZodString;
|
|
128
|
+
database: z.ZodString;
|
|
129
|
+
entity: z.ZodString;
|
|
130
|
+
landing: z.ZodObject<{
|
|
131
|
+
schema: z.ZodString;
|
|
132
|
+
relation: z.ZodString;
|
|
133
|
+
}, z.core.$strict>;
|
|
134
|
+
buffer: z.ZodObject<{
|
|
135
|
+
schema: z.ZodString;
|
|
136
|
+
relation: z.ZodString;
|
|
137
|
+
}, z.core.$strict>;
|
|
138
|
+
full_source_columns: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
139
|
+
type: z.ZodUnion<readonly [z.ZodEnum<{
|
|
140
|
+
string: "string";
|
|
141
|
+
boolean: "boolean";
|
|
142
|
+
uuid: "uuid";
|
|
143
|
+
int: "int";
|
|
144
|
+
long: "long";
|
|
145
|
+
numeric: "numeric";
|
|
146
|
+
double: "double";
|
|
147
|
+
timestamp: "timestamp";
|
|
148
|
+
date: "date";
|
|
149
|
+
json: "json";
|
|
150
|
+
}>, z.ZodEnum<{
|
|
151
|
+
float: "float";
|
|
152
|
+
timestamp_ntz: "timestamp_ntz";
|
|
153
|
+
array: "array";
|
|
154
|
+
map: "map";
|
|
155
|
+
struct: "struct";
|
|
156
|
+
binary: "binary";
|
|
157
|
+
}>, z.ZodString]>;
|
|
158
|
+
nullable: z.ZodDefault<z.ZodBoolean>;
|
|
159
|
+
key: z.ZodDefault<z.ZodBoolean>;
|
|
160
|
+
domain: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
|
|
161
|
+
description: z.ZodOptional<z.ZodString>;
|
|
162
|
+
on_violation: z.ZodDefault<z.ZodEnum<{
|
|
163
|
+
fail: "fail";
|
|
164
|
+
quarantine: "quarantine";
|
|
165
|
+
warn: "warn";
|
|
166
|
+
}>>;
|
|
167
|
+
}, z.core.$strict>>;
|
|
168
|
+
}, z.core.$strict>], "kind">>;
|
|
169
|
+
/** The transformation output this stage serves (resolution happens in graph validation). */
|
|
170
|
+
source: z.ZodObject<{
|
|
171
|
+
stage: z.ZodString;
|
|
172
|
+
output: z.ZodString;
|
|
173
|
+
catalog: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
174
|
+
default: z.ZodString;
|
|
175
|
+
by_target: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
176
|
+
}, z.core.$strict>]>>;
|
|
177
|
+
external: z.ZodOptional<z.ZodLiteral<true>>;
|
|
178
|
+
columns: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
179
|
+
type: z.ZodUnion<readonly [z.ZodEnum<{
|
|
180
|
+
string: "string";
|
|
181
|
+
boolean: "boolean";
|
|
182
|
+
uuid: "uuid";
|
|
183
|
+
int: "int";
|
|
184
|
+
long: "long";
|
|
185
|
+
numeric: "numeric";
|
|
186
|
+
double: "double";
|
|
187
|
+
timestamp: "timestamp";
|
|
188
|
+
date: "date";
|
|
189
|
+
json: "json";
|
|
190
|
+
}>, z.ZodEnum<{
|
|
191
|
+
float: "float";
|
|
192
|
+
timestamp_ntz: "timestamp_ntz";
|
|
193
|
+
array: "array";
|
|
194
|
+
map: "map";
|
|
195
|
+
struct: "struct";
|
|
196
|
+
binary: "binary";
|
|
197
|
+
}>, z.ZodString]>;
|
|
198
|
+
nullable: z.ZodDefault<z.ZodBoolean>;
|
|
199
|
+
key: z.ZodDefault<z.ZodBoolean>;
|
|
200
|
+
domain: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
|
|
201
|
+
description: z.ZodOptional<z.ZodString>;
|
|
202
|
+
on_violation: z.ZodDefault<z.ZodEnum<{
|
|
203
|
+
fail: "fail";
|
|
204
|
+
quarantine: "quarantine";
|
|
205
|
+
warn: "warn";
|
|
206
|
+
}>>;
|
|
207
|
+
}, z.core.$strict>>>;
|
|
208
|
+
}, z.core.$strict>;
|
|
209
|
+
projection: z.ZodObject<{
|
|
210
|
+
columns: z.ZodUnion<readonly [z.ZodObject<{
|
|
211
|
+
schema_ref: z.ZodString;
|
|
212
|
+
}, z.core.$strict>, z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
213
|
+
type: z.ZodUnion<readonly [z.ZodEnum<{
|
|
214
|
+
string: "string";
|
|
215
|
+
boolean: "boolean";
|
|
216
|
+
uuid: "uuid";
|
|
217
|
+
int: "int";
|
|
218
|
+
long: "long";
|
|
219
|
+
numeric: "numeric";
|
|
220
|
+
double: "double";
|
|
221
|
+
timestamp: "timestamp";
|
|
222
|
+
date: "date";
|
|
223
|
+
json: "json";
|
|
224
|
+
}>, z.ZodEnum<{
|
|
225
|
+
float: "float";
|
|
226
|
+
timestamp_ntz: "timestamp_ntz";
|
|
227
|
+
array: "array";
|
|
228
|
+
map: "map";
|
|
229
|
+
struct: "struct";
|
|
230
|
+
binary: "binary";
|
|
231
|
+
}>, z.ZodString]>;
|
|
232
|
+
nullable: z.ZodDefault<z.ZodBoolean>;
|
|
233
|
+
key: z.ZodDefault<z.ZodBoolean>;
|
|
234
|
+
domain: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
|
|
235
|
+
description: z.ZodOptional<z.ZodString>;
|
|
236
|
+
on_violation: z.ZodDefault<z.ZodEnum<{
|
|
237
|
+
fail: "fail";
|
|
238
|
+
quarantine: "quarantine";
|
|
239
|
+
warn: "warn";
|
|
240
|
+
}>>;
|
|
241
|
+
}, z.core.$strict>>]>;
|
|
242
|
+
primary_key: z.ZodArray<z.ZodString>;
|
|
243
|
+
}, z.core.$strict>;
|
|
244
|
+
sync_mode: z.ZodEnum<{
|
|
245
|
+
SNAPSHOT: "SNAPSHOT";
|
|
246
|
+
TRIGGERED: "TRIGGERED";
|
|
247
|
+
CONTINUOUS: "CONTINUOUS";
|
|
248
|
+
}>;
|
|
249
|
+
/** Refresh chains off the producer stage; omitted = platform default cadence. */
|
|
250
|
+
trigger: z.ZodOptional<z.ZodObject<{
|
|
251
|
+
after: z.ZodString;
|
|
252
|
+
}, z.core.$strict>>;
|
|
253
|
+
/** Consumer view name; ORM-only uses it solely as the stable sync naming key. */
|
|
254
|
+
expose: z.ZodObject<{
|
|
255
|
+
view: z.ZodString;
|
|
256
|
+
public_view_access: z.ZodOptional<z.ZodEnum<{
|
|
257
|
+
standard: "standard";
|
|
258
|
+
reporting: "reporting";
|
|
259
|
+
owner_only: "owner_only";
|
|
260
|
+
orm_only: "orm_only";
|
|
261
|
+
}>>;
|
|
262
|
+
orm_only_schema: z.ZodOptional<z.ZodString>;
|
|
263
|
+
orm_only_catalog: z.ZodOptional<z.ZodString>;
|
|
264
|
+
reporting_table: z.ZodOptional<z.ZodString>;
|
|
265
|
+
}, z.core.$strict>;
|
|
266
|
+
orm_binding: z.ZodOptional<z.ZodObject<{
|
|
267
|
+
namespace: z.ZodString;
|
|
268
|
+
table: z.ZodString;
|
|
269
|
+
mode: z.ZodEnum<{
|
|
270
|
+
referenced: "referenced";
|
|
271
|
+
managed: "managed";
|
|
272
|
+
}>;
|
|
273
|
+
}, z.core.$strict>>;
|
|
274
|
+
/**
|
|
275
|
+
* ORM synced-table contract this projection must satisfy
|
|
276
|
+
* (`namespace` + `table` + `content_hash`). Optional until authors pin a
|
|
277
|
+
* contract; when present, graph/provision validation fail closed on drift.
|
|
278
|
+
*/
|
|
279
|
+
satisfies: z.ZodOptional<z.ZodObject<{
|
|
280
|
+
namespace: z.ZodString;
|
|
281
|
+
table: z.ZodString;
|
|
282
|
+
content_hash: z.ZodString;
|
|
283
|
+
}, z.core.$strict>>;
|
|
284
|
+
};
|
|
285
|
+
/** Structural slice of a stage spec the serving refinement needs. */
|
|
286
|
+
export interface ServingBody {
|
|
287
|
+
readonly environments?: readonly string[];
|
|
288
|
+
readonly transport?: ServingTransport;
|
|
289
|
+
readonly sync_mode?: SyncMode;
|
|
290
|
+
readonly source: {
|
|
291
|
+
readonly stage: string;
|
|
292
|
+
readonly output: string;
|
|
293
|
+
readonly catalog?: CatalogBinding;
|
|
294
|
+
readonly external?: true;
|
|
295
|
+
readonly columns?: ColumnMap;
|
|
296
|
+
};
|
|
297
|
+
readonly projection: {
|
|
298
|
+
readonly columns: ColumnsOrRef;
|
|
299
|
+
readonly primary_key: readonly string[];
|
|
300
|
+
};
|
|
301
|
+
readonly trigger?: {
|
|
302
|
+
readonly after: string;
|
|
303
|
+
};
|
|
304
|
+
readonly expose: {
|
|
305
|
+
readonly view: string;
|
|
306
|
+
readonly public_view_access?: PublicViewAccess;
|
|
307
|
+
readonly orm_only_schema?: string;
|
|
308
|
+
readonly orm_only_catalog?: string;
|
|
309
|
+
readonly reporting_table?: string;
|
|
310
|
+
};
|
|
311
|
+
readonly orm_binding?: OrmBinding;
|
|
312
|
+
readonly satisfies?: SatisfiesBinding;
|
|
313
|
+
}
|
|
314
|
+
/** Cross-field validation for `type: serving` bodies (invoked from the envelope refinement). */
|
|
315
|
+
export declare function refineServingBody(body: ServingBody, ctx: z.RefinementCtx): void;
|
|
316
|
+
//# sourceMappingURL=serving.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serving.d.ts","sourceRoot":"","sources":["../../src/bodies/serving.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { servingTransportSchema } from '../snapshot-transport.js';
|
|
3
|
+
import { catalogBindingSchema } from '../catalog-binding.js';
|
|
4
|
+
import { GOLD_ASSET_PATTERN, PUBLIC_VIEW_PATTERN, REPORTING_TABLE_PATTERN, STAGE_ID_PATTERN, } from '../constants.js';
|
|
5
|
+
import { columnMapSchema, columnIdentifierSchema, columnsOrRefSchema, identifierSchema, isSchemaRef, } from '../columns.js';
|
|
6
|
+
import { ormMappable, ormMappingSuggestion } from '../types.js';
|
|
7
|
+
import { outputAssetNameSchema } from './transformation.js';
|
|
8
|
+
/**
|
|
9
|
+
* Serving stages replace the manual synced-table chain (synced-tables.yml →
|
|
10
|
+
* provision → UUID pinning → fan-out task → view DDL) with a declaration, and
|
|
11
|
+
* carry the ORM coupling surface: an explicit projection contract plus the
|
|
12
|
+
* `orm_binding` with the reserved `managed` mode.
|
|
13
|
+
*
|
|
14
|
+
* ## Naming-plane rules (three planes — per the adversarial ORM review)
|
|
15
|
+
*
|
|
16
|
+
* 1. **UC source name** (`gold.loans`) — the Unity Catalog relation the sync
|
|
17
|
+
* reads. Optional `source.catalog` overrides the deploy catalog for this
|
|
18
|
+
* plane only (e.g. `src_banksouth_fis.gold.loans`); the synced-table
|
|
19
|
+
* destination still lands in the deployment catalog. The ORM's `source:`
|
|
20
|
+
* field on synced tables refers to THIS plane and is display metadata —
|
|
21
|
+
* it is ambiguous against `synced_*` physical names and must never be
|
|
22
|
+
* string-matched for platform↔ORM joins.
|
|
23
|
+
* 2. **Postgres physical relation** — the Lakebase relation the sync engine
|
|
24
|
+
* creates. Captured at **provision time and stored in the registry**,
|
|
25
|
+
* never re-derived: the estate has documented derivation drift
|
|
26
|
+
* (`df_retail_customers`).
|
|
27
|
+
* 3. **Public view** (`expose.view`) — the stable consumer-facing name.
|
|
28
|
+
*
|
|
29
|
+
* `orm_binding` (namespace + table) is the **canonical join key** for all
|
|
30
|
+
* platform↔ORM checks.
|
|
31
|
+
*
|
|
32
|
+
* ## sync_mode validity (declared here, enforced at plan time)
|
|
33
|
+
*
|
|
34
|
+
* - A materialized-view source supports `SNAPSHOT` only (full refresh).
|
|
35
|
+
* - `CONTINUOUS` requires a change-data-feed-capable source table.
|
|
36
|
+
* These rules need live catalog facts, so the offline SDK documents them and
|
|
37
|
+
* the plan step (M7) enforces them; `validateSpecGraph` applies the offline
|
|
38
|
+
* subset (write-pattern sanity).
|
|
39
|
+
*/
|
|
40
|
+
export const SYNC_MODES = ['SNAPSHOT', 'TRIGGERED', 'CONTINUOUS'];
|
|
41
|
+
export const syncModeSchema = z.enum(SYNC_MODES);
|
|
42
|
+
export const PUBLIC_VIEW_ACCESS = ['standard', 'reporting', 'owner_only', 'orm_only'];
|
|
43
|
+
export const publicViewAccessSchema = z.enum(PUBLIC_VIEW_ACCESS);
|
|
44
|
+
const stageRefSchema = z.string().regex(STAGE_ID_PATTERN, 'must be a stage id (kebab-case slug)');
|
|
45
|
+
/** The served contract: projected columns + the primary key of the synced relation. */
|
|
46
|
+
export const projectionSchema = z.strictObject({
|
|
47
|
+
columns: columnsOrRefSchema,
|
|
48
|
+
primary_key: z
|
|
49
|
+
.array(columnIdentifierSchema)
|
|
50
|
+
.min(1)
|
|
51
|
+
.refine((keys) => new Set(keys).size === keys.length, 'primary_key columns must be unique'),
|
|
52
|
+
});
|
|
53
|
+
/**
|
|
54
|
+
* Join key into the Sequence ORM: the serving stage's synced relation backs
|
|
55
|
+
* the ORM table `<namespace>.<table>`.
|
|
56
|
+
*
|
|
57
|
+
* `mode: referenced` — the ORM declares the table as a synced reflection
|
|
58
|
+
* (declaration-only; the ORM engine excludes it from DDL/grants/policies).
|
|
59
|
+
* `mode: managed` is RESERVED (ORM-owned lifecycle) and rejected until the
|
|
60
|
+
* ORM-coupling milestone ships.
|
|
61
|
+
*/
|
|
62
|
+
export const ormBindingSchema = z.strictObject({
|
|
63
|
+
namespace: z
|
|
64
|
+
.string()
|
|
65
|
+
.regex(/^[a-z][a-z0-9_]{0,40}$/, 'must be an ORM namespace (lowercase, ≤41 chars)'),
|
|
66
|
+
table: identifierSchema,
|
|
67
|
+
mode: z.enum(['referenced', 'managed']),
|
|
68
|
+
});
|
|
69
|
+
/**
|
|
70
|
+
* ORM-first conformance: this projection promises to satisfy the published
|
|
71
|
+
* contract for `<namespace>.<table>` at `content_hash`. Compatibility is
|
|
72
|
+
* enforced offline by `validateSpecGraph` (when an ORM contract catalog is
|
|
73
|
+
* supplied) and at provision plan time — see `checkServingSatisfiesOrmContract`.
|
|
74
|
+
*
|
|
75
|
+
* `mode: managed` stays reserved on `orm_binding`; this binding is the
|
|
76
|
+
* hash-pinned contract reference only.
|
|
77
|
+
*/
|
|
78
|
+
export const satisfiesSchema = z.strictObject({
|
|
79
|
+
namespace: z
|
|
80
|
+
.string()
|
|
81
|
+
.regex(/^[a-z][a-z0-9_]{0,40}$/, 'must be an ORM namespace (lowercase, ≤41 chars)'),
|
|
82
|
+
table: identifierSchema,
|
|
83
|
+
content_hash: z
|
|
84
|
+
.string()
|
|
85
|
+
.regex(/^[a-f0-9]{64}$/, 'must be a sha256 hex digest (64 hex chars)'),
|
|
86
|
+
});
|
|
87
|
+
export const servingBodyShape = {
|
|
88
|
+
transport: servingTransportSchema.optional(),
|
|
89
|
+
/** The transformation output this stage serves (resolution happens in graph validation). */
|
|
90
|
+
source: z.strictObject({
|
|
91
|
+
stage: stageRefSchema,
|
|
92
|
+
output: outputAssetNameSchema,
|
|
93
|
+
/** UC catalog override for `derived.source_table` only (not the sync destination). */
|
|
94
|
+
catalog: catalogBindingSchema.optional(),
|
|
95
|
+
/**
|
|
96
|
+
* Explicitly declares a gold relation materialized outside Managed
|
|
97
|
+
* Pipelines. Its concrete contract replaces the missing producer stage.
|
|
98
|
+
*/
|
|
99
|
+
external: z.literal(true).optional(),
|
|
100
|
+
columns: columnMapSchema.optional(),
|
|
101
|
+
}),
|
|
102
|
+
projection: projectionSchema,
|
|
103
|
+
sync_mode: syncModeSchema,
|
|
104
|
+
/** Refresh chains off the producer stage; omitted = platform default cadence. */
|
|
105
|
+
trigger: z
|
|
106
|
+
.strictObject({
|
|
107
|
+
after: stageRefSchema,
|
|
108
|
+
})
|
|
109
|
+
.optional(),
|
|
110
|
+
/** Consumer view name; ORM-only uses it solely as the stable sync naming key. */
|
|
111
|
+
expose: z.strictObject({
|
|
112
|
+
view: z
|
|
113
|
+
.string()
|
|
114
|
+
.regex(/^[a-z][a-z0-9_]{0,62}\.[a-z][a-z0-9_]{0,62}$/, "must be schema.relation"),
|
|
115
|
+
/**
|
|
116
|
+
* Controls public-view access. owner_only requires enforced confinement
|
|
117
|
+
* of both the view and physical backing. Reporting views retain their
|
|
118
|
+
* reporting-consumer grants and omit ordinary reader grants. ORM-only
|
|
119
|
+
* stages create no public view and require private destinations.
|
|
120
|
+
*/
|
|
121
|
+
public_view_access: publicViewAccessSchema.optional(),
|
|
122
|
+
/** Pre-provisioned private UC/Postgres schema; never a shared serving schema. */
|
|
123
|
+
orm_only_schema: z.string().max(63).regex(/^(?:rel|fis)_orm_[a-z][a-z0-9_]*$/).optional(),
|
|
124
|
+
orm_only_catalog: z.string().max(63).regex(/^dev_[a-z][a-z0-9_]*$/).optional(),
|
|
125
|
+
/**
|
|
126
|
+
* Optional reporting-tool compatibility relation. The platform creates
|
|
127
|
+
* this view in the named Lakebase schema over the captured sync relation.
|
|
128
|
+
*/
|
|
129
|
+
reporting_table: z
|
|
130
|
+
.string()
|
|
131
|
+
.regex(REPORTING_TABLE_PATTERN, "must match 'fis_reports.<table>'")
|
|
132
|
+
.optional(),
|
|
133
|
+
}),
|
|
134
|
+
orm_binding: ormBindingSchema.optional(),
|
|
135
|
+
/**
|
|
136
|
+
* ORM synced-table contract this projection must satisfy
|
|
137
|
+
* (`namespace` + `table` + `content_hash`). Optional until authors pin a
|
|
138
|
+
* contract; when present, graph/provision validation fail closed on drift.
|
|
139
|
+
*/
|
|
140
|
+
satisfies: satisfiesSchema.optional(),
|
|
141
|
+
};
|
|
142
|
+
/** Cross-field validation for `type: serving` bodies (invoked from the envelope refinement). */
|
|
143
|
+
export function refineServingBody(body, ctx) {
|
|
144
|
+
refineServingExposure({ expose: body.expose, ctx });
|
|
145
|
+
refineServingTransport({ body, ctx });
|
|
146
|
+
if (body.expose.public_view_access === 'orm_only') {
|
|
147
|
+
const namespace = body.orm_binding?.namespace;
|
|
148
|
+
const privateSchema = namespace === 'banksouth_fis' ? /^fis_orm_[a-z][a-z0-9_]*$/ : /^rel_orm_[a-z][a-z0-9_]*$/;
|
|
149
|
+
if (!['banksouth_relationships', 'banksouth_fis'].includes(namespace ?? '') || body.orm_binding?.mode !== 'referenced' ||
|
|
150
|
+
!privateSchema.test(body.expose.orm_only_schema ?? '') || !body.expose.orm_only_catalog || body.expose.reporting_table || body.expose.view.slice('public.'.length).length > 56) {
|
|
151
|
+
ctx.addIssue({ code: 'custom', path: ['expose'], message: 'ORM-only serving requires a referenced Relationships or FIS binding, its private orm_only_catalog and namespace-specific orm_only_schema, a sync naming key of at most 56 characters, and no reporting exposure' });
|
|
152
|
+
}
|
|
153
|
+
if (namespace === 'banksouth_fis') {
|
|
154
|
+
const sourceColumns = Object.keys(body.source.columns ?? {}).sort();
|
|
155
|
+
const projectionColumns = isSchemaRef(body.projection.columns) ? [] : Object.keys(body.projection.columns).sort();
|
|
156
|
+
if (body.environments?.length !== 1 || body.environments[0] !== 'staging' || !body.source.external || body.trigger ||
|
|
157
|
+
body.sync_mode !== 'SNAPSHOT' || !body.satisfies || sourceColumns.length === 0 ||
|
|
158
|
+
sourceColumns.length !== projectionColumns.length || sourceColumns.some((column, index) => column !== projectionColumns[index])) {
|
|
159
|
+
ctx.addIssue({ code: 'custom', path: ['expose'], message: 'FIS ORM-only serving requires staging-only manual external SNAPSHOTs with the complete source projection and an ORM contract pin' });
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
else if (body.expose.orm_only_schema !== undefined || body.expose.orm_only_catalog !== undefined) {
|
|
164
|
+
ctx.addIssue({ code: 'custom', path: ['expose'], message: 'Private catalog/schema destinations are only valid with ORM-only serving' });
|
|
165
|
+
}
|
|
166
|
+
if (body.source.external && !body.source.columns) {
|
|
167
|
+
ctx.addIssue({
|
|
168
|
+
code: 'custom',
|
|
169
|
+
path: ['source', 'columns'],
|
|
170
|
+
message: 'external serving sources must declare columns',
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
if (!body.source.external && body.source.columns) {
|
|
174
|
+
ctx.addIssue({
|
|
175
|
+
code: 'custom',
|
|
176
|
+
path: ['source', 'columns'],
|
|
177
|
+
message: 'source.columns is only valid when source.external is true',
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
if (body.source.external && body.trigger) {
|
|
181
|
+
ctx.addIssue({
|
|
182
|
+
code: 'custom',
|
|
183
|
+
path: ['trigger'],
|
|
184
|
+
message: 'external serving sources cannot declare trigger.after',
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
else if (body.trigger && body.trigger.after !== body.source.stage) {
|
|
188
|
+
// A serving stage syncs its producer's output; chaining refresh off any
|
|
189
|
+
// other stage would run syncs that miss source updates. Alternate
|
|
190
|
+
// chaining semantics (e.g. after a downstream QA gate) are a future
|
|
191
|
+
// extension — until modeled, the trigger must name the producer.
|
|
192
|
+
ctx.addIssue({
|
|
193
|
+
code: 'custom',
|
|
194
|
+
path: ['trigger', 'after'],
|
|
195
|
+
message: `trigger.after must equal source.stage ('${body.source.stage}') — serving refresh chains off its producer`,
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
if (body.orm_binding) {
|
|
199
|
+
if (body.orm_binding.mode === 'managed') {
|
|
200
|
+
ctx.addIssue({
|
|
201
|
+
code: 'custom',
|
|
202
|
+
path: ['orm_binding', 'mode'],
|
|
203
|
+
message: "orm_binding mode 'managed' is reserved, not yet supported — ORM-managed serving lifecycle has not shipped (use 'referenced')",
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
if (!GOLD_ASSET_PATTERN.test(body.source.output)) {
|
|
207
|
+
// The ORM restricts synced reflected sources to `^gold\.` (SYNCED_SOURCE_PATTERN).
|
|
208
|
+
// Whether per-domain schemas may ever bind non-gold outputs is an
|
|
209
|
+
// ORM-owner decision — no non-gold binding ships before that decision.
|
|
210
|
+
ctx.addIssue({
|
|
211
|
+
code: 'custom',
|
|
212
|
+
path: ['source', 'output'],
|
|
213
|
+
message: `orm_binding requires the source output to be 'gold.*' (the ORM restricts synced sources to the gold layer) — got '${body.source.output}'`,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
if (!isSchemaRef(body.projection.columns)) {
|
|
218
|
+
const columns = body.projection.columns;
|
|
219
|
+
for (const key of body.projection.primary_key) {
|
|
220
|
+
const column = columns[key];
|
|
221
|
+
if (!column) {
|
|
222
|
+
ctx.addIssue({
|
|
223
|
+
code: 'custom',
|
|
224
|
+
path: ['projection', 'primary_key'],
|
|
225
|
+
message: `primary_key column '${key}' is not declared in the projection`,
|
|
226
|
+
});
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
if (column.nullable) {
|
|
230
|
+
ctx.addIssue({
|
|
231
|
+
code: 'custom',
|
|
232
|
+
path: ['projection', 'columns', key, 'nullable'],
|
|
233
|
+
message: `primary_key column '${key}' must be nullable: false`,
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (body.orm_binding || body.satisfies) {
|
|
238
|
+
for (const [name, column] of Object.entries(columns)) {
|
|
239
|
+
if (!ormMappable(column.type)) {
|
|
240
|
+
ctx.addIssue({
|
|
241
|
+
code: 'custom',
|
|
242
|
+
path: ['projection', 'columns', name, 'type'],
|
|
243
|
+
message: `column '${name}' has type '${column.type}', which is not ORM-mappable — ${ormMappingSuggestion(column.type)}`,
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
if (body.orm_binding &&
|
|
250
|
+
body.satisfies &&
|
|
251
|
+
(body.orm_binding.namespace !== body.satisfies.namespace ||
|
|
252
|
+
body.orm_binding.table !== body.satisfies.table)) {
|
|
253
|
+
ctx.addIssue({
|
|
254
|
+
code: 'custom',
|
|
255
|
+
path: ['satisfies'],
|
|
256
|
+
message: `satisfies (${body.satisfies.namespace}.${body.satisfies.table}) must name the same ` +
|
|
257
|
+
`ORM table as orm_binding (${body.orm_binding.namespace}.${body.orm_binding.table})`,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
function refineServingExposure({ expose, ctx }) {
|
|
262
|
+
if (expose.public_view_access === 'owner_only' && expose.reporting_table) {
|
|
263
|
+
ctx.addIssue({
|
|
264
|
+
code: 'custom',
|
|
265
|
+
path: ['expose', 'reporting_table'],
|
|
266
|
+
message: 'owner_only cannot expose a reporting_table (it grants consumer access)',
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
function refineServingTransport({ body, ctx }) {
|
|
271
|
+
if (body.transport?.kind === 'postgres_snapshot_landing_v1') {
|
|
272
|
+
const transport = body.transport;
|
|
273
|
+
if (body.sync_mode !== 'SNAPSHOT' || body.expose.public_view_access !== 'owner_only' ||
|
|
274
|
+
body.expose.view.startsWith('public.') || body.expose.reporting_table || body.source.external) {
|
|
275
|
+
ctx.addIssue({ code: 'custom', path: ['transport'], message: 'snapshot transport requires SNAPSHOT, a private owner_only exposure and an in-release producer' });
|
|
276
|
+
}
|
|
277
|
+
const names = [body.expose.view, `${transport.landing.schema}.${transport.landing.relation}`, `${transport.buffer.schema}.${transport.buffer.relation}`];
|
|
278
|
+
if (new Set(names).size !== 3)
|
|
279
|
+
ctx.addIssue({ code: 'custom', path: ['transport'], message: 'snapshot landing, buffer and exposure must be distinct' });
|
|
280
|
+
for (const key of body.projection.primary_key) {
|
|
281
|
+
if (!transport.full_source_columns[key] || transport.full_source_columns[key].nullable) {
|
|
282
|
+
ctx.addIssue({ code: 'custom', path: ['transport', 'full_source_columns'], message: 'snapshot PK must exist and be nonnullable in the complete raw shape' });
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
else if (!PUBLIC_VIEW_PATTERN.test(body.expose.view)) {
|
|
287
|
+
ctx.addIssue({ code: 'custom', path: ['expose', 'view'], message: "native exposure must match '^public\\.[a-z][a-z0-9_]*$'" });
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
//# sourceMappingURL=serving.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serving.js","sourceRoot":"","sources":["../../src/bodies/serving.ts"],"names":[],"mappings":"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"}
|