@google-cloud/kcmd 0.0.0-stage → 0.2.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/LICENSE +203 -0
- package/README.md +264 -2
- package/build/ts/kcmd/cli.js +20252 -0
- package/build/ts/kcmd/gcp/alloydb.d.ts +12 -0
- package/build/ts/kcmd/gcp/alloydb.js +70 -0
- package/build/ts/kcmd/gcp/api.d.ts +29 -0
- package/build/ts/kcmd/gcp/api.js +162 -0
- package/build/ts/kcmd/gcp/biglake.d.ts +18 -0
- package/build/ts/kcmd/gcp/biglake.js +59 -0
- package/build/ts/kcmd/gcp/bigquery.d.ts +57 -0
- package/build/ts/kcmd/gcp/bigquery.js +134 -0
- package/build/ts/kcmd/gcp/context.d.ts +10 -0
- package/build/ts/kcmd/gcp/context.js +74 -0
- package/build/ts/kcmd/gcp/crm.d.ts +13 -0
- package/build/ts/kcmd/gcp/crm.js +91 -0
- package/build/ts/kcmd/gcp/dataplex.d.ts +147 -0
- package/build/ts/kcmd/gcp/dataplex.js +406 -0
- package/build/ts/kcmd/gcp/index.d.ts +3 -0
- package/build/ts/kcmd/gcp/index.js +21 -0
- package/build/ts/kcmd/gcp/spanner.d.ts +73 -0
- package/build/ts/kcmd/gcp/spanner.js +126 -0
- package/build/ts/kcmd/index.d.ts +7 -0
- package/build/ts/kcmd/index.js +46 -0
- package/build/ts/kcmd/layout.d.ts +16 -0
- package/build/ts/kcmd/layout.js +31 -0
- package/build/ts/kcmd/layouts/documents.d.ts +24 -0
- package/build/ts/kcmd/layouts/documents.js +264 -0
- package/build/ts/kcmd/layouts/okf.d.ts +31 -0
- package/build/ts/kcmd/layouts/okf.js +386 -0
- package/build/ts/kcmd/layouts/semantic-model.d.ts +74 -0
- package/build/ts/kcmd/layouts/semantic-model.js +621 -0
- package/build/ts/kcmd/layouts/standard.d.ts +13 -0
- package/build/ts/kcmd/layouts/standard.js +108 -0
- package/build/ts/kcmd/manifest.d.ts +34 -0
- package/build/ts/kcmd/manifest.js +262 -0
- package/build/ts/kcmd/metadata.d.ts +25 -0
- package/build/ts/kcmd/metadata.js +8 -0
- package/build/ts/kcmd/okf/catalog_residue.d.ts +14 -0
- package/build/ts/kcmd/okf/catalog_residue.js +124 -0
- package/build/ts/kcmd/okf/concept.d.ts +14 -0
- package/build/ts/kcmd/okf/concept.js +110 -0
- package/build/ts/kcmd/okf/concept_to_entry.d.ts +10 -0
- package/build/ts/kcmd/okf/concept_to_entry.js +281 -0
- package/build/ts/kcmd/okf/init_okf_workspace.d.ts +15 -0
- package/build/ts/kcmd/okf/init_okf_workspace.js +113 -0
- package/build/ts/kcmd/okf/links.d.ts +23 -0
- package/build/ts/kcmd/okf/links.js +468 -0
- package/build/ts/kcmd/okf/okf_metadata.d.ts +12 -0
- package/build/ts/kcmd/okf/okf_metadata.js +99 -0
- package/build/ts/kcmd/semantic/bigquery.d.ts +22 -0
- package/build/ts/kcmd/semantic/bigquery.js +469 -0
- package/build/ts/kcmd/semantic/binding.d.ts +3 -0
- package/build/ts/kcmd/semantic/binding.js +92 -0
- package/build/ts/kcmd/semantic/catalog_entry.d.ts +24 -0
- package/build/ts/kcmd/semantic/catalog_entry.js +35 -0
- package/build/ts/kcmd/semantic/converters/owl/convert.d.ts +26 -0
- package/build/ts/kcmd/semantic/converters/owl/convert.js +41 -0
- package/build/ts/kcmd/semantic/converters/owl/model.d.ts +98 -0
- package/build/ts/kcmd/semantic/converters/owl/model.js +30 -0
- package/build/ts/kcmd/semantic/converters/owl/parse.d.ts +11 -0
- package/build/ts/kcmd/semantic/converters/owl/parse.js +634 -0
- package/build/ts/kcmd/semantic/converters/owl/to_ir.d.ts +19 -0
- package/build/ts/kcmd/semantic/converters/owl/to_ir.js +390 -0
- package/build/ts/kcmd/semantic/deploy_bigquery.d.ts +20 -0
- package/build/ts/kcmd/semantic/deploy_bigquery.js +226 -0
- package/build/ts/kcmd/semantic/deploy_knowledge_catalog.d.ts +104 -0
- package/build/ts/kcmd/semantic/deploy_knowledge_catalog.js +1367 -0
- package/build/ts/kcmd/semantic/deploy_spanner.d.ts +15 -0
- package/build/ts/kcmd/semantic/deploy_spanner.js +150 -0
- package/build/ts/kcmd/semantic/deployment_target.d.ts +93 -0
- package/build/ts/kcmd/semantic/deployment_target.js +379 -0
- package/build/ts/kcmd/semantic/graph_ddl.d.ts +44 -0
- package/build/ts/kcmd/semantic/graph_ddl.js +656 -0
- package/build/ts/kcmd/semantic/import_model.d.ts +72 -0
- package/build/ts/kcmd/semantic/import_model.js +1698 -0
- package/build/ts/kcmd/semantic/ir.d.ts +589 -0
- package/build/ts/kcmd/semantic/ir.js +247 -0
- package/build/ts/kcmd/semantic/kc_actions.d.ts +45 -0
- package/build/ts/kcmd/semantic/kc_actions.js +531 -0
- package/build/ts/kcmd/semantic/kc_constraints.d.ts +44 -0
- package/build/ts/kcmd/semantic/kc_constraints.js +279 -0
- package/build/ts/kcmd/semantic/kc_converter.d.ts +37 -0
- package/build/ts/kcmd/semantic/kc_converter.js +839 -0
- package/build/ts/kcmd/semantic/kc_custom_types.d.ts +63 -0
- package/build/ts/kcmd/semantic/kc_custom_types.js +751 -0
- package/build/ts/kcmd/semantic/kc_entries.d.ts +155 -0
- package/build/ts/kcmd/semantic/kc_entries.js +284 -0
- package/build/ts/kcmd/semantic/kc_ids.d.ts +102 -0
- package/build/ts/kcmd/semantic/kc_ids.js +188 -0
- package/build/ts/kcmd/semantic/knowledge_catalog.d.ts +29 -0
- package/build/ts/kcmd/semantic/knowledge_catalog.js +960 -0
- package/build/ts/kcmd/semantic/loader.d.ts +258 -0
- package/build/ts/kcmd/semantic/loader.js +3576 -0
- package/build/ts/kcmd/semantic/names.d.ts +10 -0
- package/build/ts/kcmd/semantic/names.js +85 -0
- package/build/ts/kcmd/semantic/osi_converter.d.ts +60 -0
- package/build/ts/kcmd/semantic/osi_converter.js +910 -0
- package/build/ts/kcmd/semantic/parameters.d.ts +19 -0
- package/build/ts/kcmd/semantic/parameters.js +171 -0
- package/build/ts/kcmd/semantic/pull_kc.d.ts +10 -0
- package/build/ts/kcmd/semantic/pull_kc.js +272 -0
- package/build/ts/kcmd/semantic/resolve_inheritance.d.ts +59 -0
- package/build/ts/kcmd/semantic/resolve_inheritance.js +346 -0
- package/build/ts/kcmd/semantic/resolve_profiles.d.ts +291 -0
- package/build/ts/kcmd/semantic/resolve_profiles.js +2003 -0
- package/build/ts/kcmd/semantic/runtime/agent_tools.d.ts +93 -0
- package/build/ts/kcmd/semantic/runtime/agent_tools.js +243 -0
- package/build/ts/kcmd/semantic/runtime/dialect.d.ts +13 -0
- package/build/ts/kcmd/semantic/runtime/dialect.js +39 -0
- package/build/ts/kcmd/semantic/runtime/runtime.d.ts +88 -0
- package/build/ts/kcmd/semantic/runtime/runtime.js +301 -0
- package/build/ts/kcmd/semantic/runtime/store.d.ts +112 -0
- package/build/ts/kcmd/semantic/runtime/store.js +344 -0
- package/build/ts/kcmd/semantic/skills.d.ts +110 -0
- package/build/ts/kcmd/semantic/skills.js +697 -0
- package/build/ts/kcmd/semantic/source_dialect.d.ts +17 -0
- package/build/ts/kcmd/semantic/source_dialect.js +311 -0
- package/build/ts/kcmd/semantic/source_entries.d.ts +12 -0
- package/build/ts/kcmd/semantic/source_entries.js +341 -0
- package/build/ts/kcmd/semantic/spanner.d.ts +18 -0
- package/build/ts/kcmd/semantic/spanner.js +60 -0
- package/build/ts/kcmd/semantic/sql_expr_utils.d.ts +23 -0
- package/build/ts/kcmd/semantic/sql_expr_utils.js +394 -0
- package/build/ts/kcmd/semantic/sql_identifiers.d.ts +6 -0
- package/build/ts/kcmd/semantic/sql_identifiers.js +267 -0
- package/build/ts/kcmd/semantic/sql_parser.d.ts +47 -0
- package/build/ts/kcmd/semantic/sql_parser.js +400 -0
- package/build/ts/kcmd/semantic/transpile.d.ts +76 -0
- package/build/ts/kcmd/semantic/transpile.js +581 -0
- package/build/ts/kcmd/semantic/validate.d.ts +70 -0
- package/build/ts/kcmd/semantic/validate.js +2266 -0
- package/build/ts/kcmd/semantic/yaml_options.d.ts +6 -0
- package/build/ts/kcmd/semantic/yaml_options.js +58 -0
- package/build/ts/kcmd/semantic/yaml_update.d.ts +26 -0
- package/build/ts/kcmd/semantic/yaml_update.js +782 -0
- package/build/ts/kcmd/snapshot.d.ts +37 -0
- package/build/ts/kcmd/snapshot.js +386 -0
- package/build/ts/kcmd/source.d.ts +31 -0
- package/build/ts/kcmd/source.js +119 -0
- package/build/ts/kcmd/sources/bq-dataset.d.ts +17 -0
- package/build/ts/kcmd/sources/bq-dataset.js +131 -0
- package/build/ts/kcmd/sources/entrygroup.d.ts +21 -0
- package/build/ts/kcmd/sources/entrygroup.js +83 -0
- package/build/ts/kcmd/sources/kb.d.ts +21 -0
- package/build/ts/kcmd/sources/kb.js +82 -0
- package/build/ts/kcmd/sources/semantic-model.d.ts +18 -0
- package/build/ts/kcmd/sources/semantic-model.js +48 -0
- package/build/ts/kcmd/sync.d.ts +35 -0
- package/build/ts/kcmd/sync.js +734 -0
- package/package.json +62 -4
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Defines the Semantic Model intermediate representation (IR).
|
|
3
|
+
//
|
|
4
|
+
// The IR is the in-memory contract for a semantic model. It represents
|
|
5
|
+
// semantics only: a graph of entities (nodes) connected by relationships
|
|
6
|
+
// (edges), plus model-level metrics.
|
|
7
|
+
//
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.CONSTRAINT_SEVERITIES = exports.VIOLATION_EFFECTS = exports.SQL_EXECUTOR_VERBS = exports.CONCEPT_OPERATIONS = exports.FIELD_DEFINITION_KEYS = exports.FIELD_BINDING_KEYS = exports.DATA_TYPES = exports.ALLOWED_DIALECTS = void 0;
|
|
10
|
+
exports.normalizeDataType = normalizeDataType;
|
|
11
|
+
exports.isTimeDimension = isTimeDimension;
|
|
12
|
+
exports.fieldBinding = fieldBinding;
|
|
13
|
+
exports.isFieldBound = isFieldBound;
|
|
14
|
+
exports.coversKey = coversKey;
|
|
15
|
+
exports.expressionForDialect = expressionForDialect;
|
|
16
|
+
exports.ALLOWED_DIALECTS = [
|
|
17
|
+
'ANSI_SQL', 'BIGQUERY', 'SPANNER', 'MYSQL',
|
|
18
|
+
'POSTGRES', 'ALLOYDB', 'SQLSERVER', 'SNOWFLAKE', 'DATABRICKS',
|
|
19
|
+
];
|
|
20
|
+
/**
|
|
21
|
+
* The open format's `datatype` vocabulary, mirroring Apache Ossie's `DataType`:
|
|
22
|
+
* a CLOSED, case-sensitive set of logical types, independent of physical
|
|
23
|
+
* representation. It is optional; omit it when the type is unknown. `Opaque`
|
|
24
|
+
* marks an unknown type: the loader reads it as no type, and the catalog stores
|
|
25
|
+
* it where a type is required. No custom extension supplies a real type for
|
|
26
|
+
* it. The loader enforces this set at parse time, so a `type` on the IR is
|
|
27
|
+
* always one of these.
|
|
28
|
+
*/
|
|
29
|
+
exports.DATA_TYPES = [
|
|
30
|
+
'String',
|
|
31
|
+
'Integer',
|
|
32
|
+
'Decimal',
|
|
33
|
+
'Float',
|
|
34
|
+
'Boolean',
|
|
35
|
+
'Date',
|
|
36
|
+
'Time',
|
|
37
|
+
'DateTime',
|
|
38
|
+
'DateTimeTz',
|
|
39
|
+
'Opaque',
|
|
40
|
+
];
|
|
41
|
+
const CANONICAL_DATA_TYPES = exports.DATA_TYPES.filter((t) => t !== 'Opaque');
|
|
42
|
+
/**
|
|
43
|
+
* Normalizes a raw `datatype` string according to the document's flavor.
|
|
44
|
+
*
|
|
45
|
+
* In `0.2.0.dev0`, matching is strictly case-sensitive. In `0.2.0.dev0/google`,
|
|
46
|
+
* matching is case-insensitive and returns the canonical spelling. In both
|
|
47
|
+
* flavors, an omitted `datatype` and `Opaque` normalize to `type: undefined`.
|
|
48
|
+
*/
|
|
49
|
+
function normalizeDataType(raw, version) {
|
|
50
|
+
if (raw === undefined) {
|
|
51
|
+
return { ok: true, type: undefined };
|
|
52
|
+
}
|
|
53
|
+
const caseInsensitive = version === '0.2.0.dev0/google';
|
|
54
|
+
const matches = (a, b) => caseInsensitive ? a.toLowerCase() === b.toLowerCase() : a === b;
|
|
55
|
+
if (matches(raw, 'Opaque')) {
|
|
56
|
+
return { ok: true, type: undefined };
|
|
57
|
+
}
|
|
58
|
+
const found = CANONICAL_DATA_TYPES.find(t => matches(raw, t));
|
|
59
|
+
if (found) {
|
|
60
|
+
return { ok: true, type: found };
|
|
61
|
+
}
|
|
62
|
+
return { ok: false };
|
|
63
|
+
}
|
|
64
|
+
// The temporal subset of DataType (Date / Time / DateTime / DateTimeTz); a
|
|
65
|
+
// field of one of these types is a time dimension by default (see
|
|
66
|
+
// isTimeDimension).
|
|
67
|
+
const TEMPORAL_TYPES = new Set([
|
|
68
|
+
'Date',
|
|
69
|
+
'Time',
|
|
70
|
+
'DateTime',
|
|
71
|
+
'DateTimeTz',
|
|
72
|
+
]);
|
|
73
|
+
/**
|
|
74
|
+
* A field's effective temporal-dimension role, mirroring the open format's
|
|
75
|
+
* `is_time_dimension()` (e.g. Apache Ossie's `OSIField`): a field must carry
|
|
76
|
+
* `dimension` metadata to be a dimension at all; within it an explicit `isTime`
|
|
77
|
+
* takes precedence, otherwise the role defaults from a temporal `type`.
|
|
78
|
+
*/
|
|
79
|
+
function isTimeDimension(field) {
|
|
80
|
+
if (!field.dimension)
|
|
81
|
+
return false;
|
|
82
|
+
if (field.dimension.isTime !== undefined)
|
|
83
|
+
return field.dimension.isTime;
|
|
84
|
+
return field.type !== undefined && TEMPORAL_TYPES.has(field.type);
|
|
85
|
+
}
|
|
86
|
+
// The physical column (or SQL) a field binds to when no engine is named, or
|
|
87
|
+
// undefined when it carries neither expression. A field's target/canonical
|
|
88
|
+
// `expression` wins; a field awaiting transpilation falls back to its imported
|
|
89
|
+
// vendor expression, which still names a real column. Undefined here is not
|
|
90
|
+
// the same as unbound: a field bound only through a `dialects` list has no
|
|
91
|
+
// text here yet counts as bound (see isFieldBound). The graph generators ask
|
|
92
|
+
// for their own engine's text through `expressionForDialect` instead.
|
|
93
|
+
function fieldBinding(field) {
|
|
94
|
+
return field.expression ?? field.importedExpression;
|
|
95
|
+
}
|
|
96
|
+
// The properties of a field that bind it to a column, and the ones that define
|
|
97
|
+
// what it is. A subtype that redeclares an inherited field may set binding
|
|
98
|
+
// properties and never definition properties. Together with `name` they are
|
|
99
|
+
// every property a field has; the check below fails to compile if a property
|
|
100
|
+
// is added to Field without being placed in one list or the other.
|
|
101
|
+
exports.FIELD_BINDING_KEYS = [
|
|
102
|
+
'expression', 'dialects', 'stringForm', 'importedExpression',
|
|
103
|
+
'importedDialect',
|
|
104
|
+
];
|
|
105
|
+
exports.FIELD_DEFINITION_KEYS = [
|
|
106
|
+
'type', 'label', 'dimension', 'description', 'aiContext', 'customExtensions',
|
|
107
|
+
];
|
|
108
|
+
const everyFieldKeyListed = true;
|
|
109
|
+
void everyFieldKeyListed;
|
|
110
|
+
/**
|
|
111
|
+
* Whether a field is bound to a column under the current binding: it carries an
|
|
112
|
+
* expression, an imported vendor expression, or a non-empty dialect list.
|
|
113
|
+
* `stringForm` and `importedDialect` describe a binding and are not one on
|
|
114
|
+
* their own. Inheritance, profile pruning and push validation use this test.
|
|
115
|
+
* A graph generator asks a narrower question, whether the field has SQL for its
|
|
116
|
+
* engine (see expressionForDialect), so a bound field can still be left out of
|
|
117
|
+
* one engine's graph.
|
|
118
|
+
*/
|
|
119
|
+
function isFieldBound(field) {
|
|
120
|
+
return fieldBinding(field) !== undefined || (field.dialects?.length ?? 0) > 0;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Whether a relationship's `to_columns` cover the primary key or a unique key.
|
|
124
|
+
* A key is covered when every one of its columns is among `to_columns`, so a
|
|
125
|
+
* superset of a key covers it, since each row still matches at most one target
|
|
126
|
+
* row. Column names compare as BigQuery compares them: ignoring case, and
|
|
127
|
+
* without the backticks that only quote a name.
|
|
128
|
+
*/
|
|
129
|
+
function coversKey(toColumns, primaryKey, uniqueKeys) {
|
|
130
|
+
const columnKey = (c) => c.replace(/^`(.*)`$/, '$1').toLowerCase();
|
|
131
|
+
const has = new Set(toColumns.map(columnKey));
|
|
132
|
+
return [primaryKey, ...uniqueKeys].some(key => key.length > 0 && key.every(c => has.has(columnKey(c))));
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Selects the SQL expression for a target engine from a Field or Metric.
|
|
136
|
+
*
|
|
137
|
+
* With a non-empty `dialects` list, returns the entry matching `targetDialect`;
|
|
138
|
+
* failing that, and where the target is not already `ANSI_SQL`, falls back to
|
|
139
|
+
* the `ANSI_SQL` entry; failing both, returns `undefined`. With `dialects`
|
|
140
|
+
* empty or absent, returns `item.importedExpression` when `importedDialect` is
|
|
141
|
+
* the target, and `item.expression` otherwise.
|
|
142
|
+
*/
|
|
143
|
+
function expressionForDialect(item, targetDialect) {
|
|
144
|
+
if (item.dialects && item.dialects.length > 0) {
|
|
145
|
+
const exact = item.dialects.find(d => d.dialect === targetDialect);
|
|
146
|
+
if (exact)
|
|
147
|
+
return exact.expression;
|
|
148
|
+
if (targetDialect !== 'ANSI_SQL') {
|
|
149
|
+
const ansi = item.dialects.find(d => d.dialect === 'ANSI_SQL');
|
|
150
|
+
if (ansi)
|
|
151
|
+
return ansi.expression;
|
|
152
|
+
}
|
|
153
|
+
return undefined;
|
|
154
|
+
}
|
|
155
|
+
if (item.importedExpression !== undefined &&
|
|
156
|
+
item.importedDialect === targetDialect) {
|
|
157
|
+
return item.importedExpression;
|
|
158
|
+
}
|
|
159
|
+
return item.expression;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* What an action does to a concept it affects.
|
|
163
|
+
*
|
|
164
|
+
* One vocabulary covers entities and relationships alike, because both admit
|
|
165
|
+
* the same three acts. An edge is not only added and removed: a many-to-many
|
|
166
|
+
* relationship is backed by a junction table with fields of its own (see
|
|
167
|
+
* Association), so modifying an enrollment's grade is as ordinary as modifying
|
|
168
|
+
* an order's total. Splitting the vocabulary by kind would make that change
|
|
169
|
+
* inexpressible and would buy a policy predicate nothing.
|
|
170
|
+
*/
|
|
171
|
+
exports.CONCEPT_OPERATIONS = ['create', 'modify', 'delete'];
|
|
172
|
+
// The verbs a SQL executor's statement may begin with. A statement is one write,
|
|
173
|
+
// so there is no SELECT here and no DDL: a statement that reads is a query and
|
|
174
|
+
// belongs in a metric, and a statement that reshapes the schema is not an action.
|
|
175
|
+
exports.SQL_EXECUTOR_VERBS = ['INSERT', 'UPDATE', 'DELETE'];
|
|
176
|
+
/**
|
|
177
|
+
* What a violated constraint does to the write that tripped it.
|
|
178
|
+
*
|
|
179
|
+
* - `reject` the write is refused. Nobody is allowed to approve it, which
|
|
180
|
+
* is what makes the rule an invariant rather than a policy.
|
|
181
|
+
* - `escalate` the write is held and a person decides. The rule is a business
|
|
182
|
+
* threshold, so somebody is allowed to say yes.
|
|
183
|
+
* - `warn` the write proceeds and the violation is reported.
|
|
184
|
+
*
|
|
185
|
+
* An engine reading the catalog needs this in order to route. Without it every
|
|
186
|
+
* rule publishes with the same shape, and a $30 credit that needs a supervisor
|
|
187
|
+
* is indistinguishable from one that is simply forbidden.
|
|
188
|
+
*
|
|
189
|
+
* This is a disposition, not a magnitude, and the two are deliberately separate
|
|
190
|
+
* keys. `escalate` is not "between" reject and warn on a scale of badness: it is
|
|
191
|
+
* a different control flow, and what it really states is that an approver
|
|
192
|
+
* exists. Two rules can be equally grave -- both guarding a million-dollar write
|
|
193
|
+
* -- and differ only in whether anyone in the organization is entitled to say
|
|
194
|
+
* yes. See CONSTRAINT_SEVERITIES for the magnitude.
|
|
195
|
+
*
|
|
196
|
+
* `escalate` names that an approver exists. It does not name who: an approver
|
|
197
|
+
* role is not modeled yet.
|
|
198
|
+
*
|
|
199
|
+
* The consequence is a field rather than something a `judgment` states in its
|
|
200
|
+
* own prose, because three things need it without running a judge. An
|
|
201
|
+
* unrunnable judge -- none configured, a failed call, a timeout -- still has to
|
|
202
|
+
* route the breach it could not evaluate. A search for the rules that can stop
|
|
203
|
+
* a write cannot read prose. And a policy DSL states its effect in the rule
|
|
204
|
+
* head, so a rule whose consequence is only implied by its wording cannot be
|
|
205
|
+
* lowered into OPA or Cedar.
|
|
206
|
+
*
|
|
207
|
+
* A judgment may declare any of the three, `reject` included. What settles a
|
|
208
|
+
* judgment can decide two identical proposals differently, and `reject` leaves
|
|
209
|
+
* no appeal, so that pairing is the riskiest thing this model can express. It
|
|
210
|
+
* is still a bet an organization is entitled to place, and refusing to
|
|
211
|
+
* represent it would move the policy out of the catalog rather than prevent it.
|
|
212
|
+
* It is made auditable instead: `evaluation` publishes `judged` beside the
|
|
213
|
+
* word, so "unappealable rules settled by a model" is one query. `onViolation`
|
|
214
|
+
* is required on a judgment rather than defaulted, because a forgotten word
|
|
215
|
+
* would produce exactly that pairing silently.
|
|
216
|
+
*
|
|
217
|
+
* A constraint's word is the consequence of the one condition it states. A
|
|
218
|
+
* policy whose conditions carry different consequences is written as several
|
|
219
|
+
* constraints, which `guards` on an action lists together; the strictest
|
|
220
|
+
* consequence among the violated ones is what the action does. See
|
|
221
|
+
* docs/semantic-model/actions.md for a worked policy.
|
|
222
|
+
*
|
|
223
|
+
* STATUS: the declared word is published, read back, and routed on for the
|
|
224
|
+
* rules something settles. A judgment is settled where an action names it in
|
|
225
|
+
* `guards`, and `warn` reports while `reject` and `escalate` stop the call;
|
|
226
|
+
* `escalate` says so in the refusal, because nothing here has an approver to
|
|
227
|
+
* route to. An expression is still text nothing computes, so its word decides
|
|
228
|
+
* nothing yet.
|
|
229
|
+
*/
|
|
230
|
+
exports.VIOLATION_EFFECTS = ['reject', 'escalate', 'warn'];
|
|
231
|
+
/**
|
|
232
|
+
* How grave a violation of a constraint is, independent of what the engine does
|
|
233
|
+
* about it.
|
|
234
|
+
*
|
|
235
|
+
* Ranking and reporting want this: which of forty violations in a batch to show
|
|
236
|
+
* a human first, which to page on. Enforcement does not -- that is
|
|
237
|
+
* `onViolation`, and the split is the point. A `low` rule may still be an
|
|
238
|
+
* absolute `reject`, and a `critical` one may be a `warn` because the
|
|
239
|
+
* organization is not ready to block on it yet.
|
|
240
|
+
*
|
|
241
|
+
* The scale is the ordinary four-point one, and it avoids `warning` on purpose:
|
|
242
|
+
* a severity called `warning` sitting beside an effect called `warn` would read
|
|
243
|
+
* as the same statement made twice.
|
|
244
|
+
*
|
|
245
|
+
* STATUS: authored, published and read back. Nothing ranks or routes on it yet.
|
|
246
|
+
*/
|
|
247
|
+
exports.CONSTRAINT_SEVERITIES = ['critical', 'high', 'medium', 'low'];
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Entry } from '../gcp/dataplex';
|
|
2
|
+
import { Action, SemanticModel } from './ir';
|
|
3
|
+
export declare function actionEntryTypeName(dest: {
|
|
4
|
+
project: string;
|
|
5
|
+
}): string;
|
|
6
|
+
export declare function actionAspectTypeName(dest: {
|
|
7
|
+
project: string;
|
|
8
|
+
}): string;
|
|
9
|
+
export declare function actionAspectKey(dest: {
|
|
10
|
+
project: string;
|
|
11
|
+
}): string;
|
|
12
|
+
export interface ActionEmitContext {
|
|
13
|
+
project: string;
|
|
14
|
+
entry(entryId: string): string;
|
|
15
|
+
anchor: string;
|
|
16
|
+
claim(entryId: string, label: string): boolean;
|
|
17
|
+
publishedEntities: Set<string>;
|
|
18
|
+
}
|
|
19
|
+
export declare function actionEntryId(modelId: string, actionName: string): string;
|
|
20
|
+
export declare function actionOwnedPrefix(modelId: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* One entry per action, to append to the model's entries.
|
|
23
|
+
*
|
|
24
|
+
* Empty when the model declares no actions, so a model without actions is
|
|
25
|
+
* unchanged from before actions existed. Warns once when it is non-empty:
|
|
26
|
+
* actions reach Knowledge Catalog and nowhere else, which is worth saying out
|
|
27
|
+
* loud on a push that also deploys a graph.
|
|
28
|
+
*/
|
|
29
|
+
export declare function actionEntries(model: SemanticModel, modelId: string, ctx: ActionEmitContext, warnings: string[]): Entry[];
|
|
30
|
+
export declare function isActionEntry(entry: Entry): boolean;
|
|
31
|
+
export declare function actionAspectTypes(entryTypeBase: string): string[];
|
|
32
|
+
/**
|
|
33
|
+
* Recovers one action from its entry, the inverse of actionEntries.
|
|
34
|
+
*
|
|
35
|
+
* A parameter recovers exactly what was stored, projection and all. Nothing is
|
|
36
|
+
* re-derived here: a derived parameter's type was resolved once, at load, and
|
|
37
|
+
* the aspect carries the answer, so a pull that recovered the concept and one
|
|
38
|
+
* that did not produce the same parameter rather than two different ones.
|
|
39
|
+
*
|
|
40
|
+
* An entry with NO executor recovers as an action with none: that is a legal
|
|
41
|
+
* published state, not damage. An entry whose executor names a kind but lacks
|
|
42
|
+
* the coordinates that kind needs is malformed, and returns undefined with a
|
|
43
|
+
* warning, so one bad entry degrades itself rather than the pull.
|
|
44
|
+
*/
|
|
45
|
+
export declare function readAction(entry: Entry, warnings: string[]): Action | undefined;
|