@x12i/memorix-service 3.12.4 → 3.13.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 +1 -1
- package/dist/anomaly/catalog.d.ts +4 -0
- package/dist/anomaly/catalog.d.ts.map +1 -0
- package/dist/anomaly/catalog.js +315 -0
- package/dist/anomaly/catalog.js.map +1 -0
- package/dist/anomaly/descriptors.d.ts +11 -0
- package/dist/anomaly/descriptors.d.ts.map +1 -0
- package/dist/anomaly/descriptors.js +113 -0
- package/dist/anomaly/descriptors.js.map +1 -0
- package/dist/anomaly/index.d.ts +6 -0
- package/dist/anomaly/index.d.ts.map +1 -0
- package/dist/anomaly/index.js +5 -0
- package/dist/anomaly/index.js.map +1 -0
- package/dist/anomaly/records.d.ts +28 -0
- package/dist/anomaly/records.d.ts.map +1 -0
- package/dist/anomaly/records.js +384 -0
- package/dist/anomaly/records.js.map +1 -0
- package/dist/anomaly/types.d.ts +116 -0
- package/dist/anomaly/types.d.ts.map +1 -0
- package/dist/anomaly/types.js +24 -0
- package/dist/anomaly/types.js.map +1 -0
- package/dist/anomaly/values.d.ts +31 -0
- package/dist/anomaly/values.d.ts.map +1 -0
- package/dist/anomaly/values.js +171 -0
- package/dist/anomaly/values.js.map +1 -0
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +12 -0
- package/dist/app.js.map +1 -1
- package/dist/catalog-bridge.d.ts +18 -0
- package/dist/catalog-bridge.d.ts.map +1 -1
- package/dist/catalog-bridge.js +85 -0
- package/dist/catalog-bridge.js.map +1 -1
- package/dist/errors.d.ts +5 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +18 -0
- package/dist/errors.js.map +1 -1
- package/dist/knowledge-upstream.d.ts +32 -0
- package/dist/knowledge-upstream.d.ts.map +1 -1
- package/dist/knowledge-upstream.js +86 -2
- package/dist/knowledge-upstream.js.map +1 -1
- package/dist/mcp/nexum-tools.d.ts +1 -1
- package/dist/mcp/nexum-tools.d.ts.map +1 -1
- package/dist/mcp/nexum-tools.js +39 -22
- package/dist/mcp/nexum-tools.js.map +1 -1
- package/dist/nexum-analysis/enqueue.d.ts.map +1 -1
- package/dist/nexum-analysis/enqueue.js +2 -1
- package/dist/nexum-analysis/enqueue.js.map +1 -1
- package/dist/nexum-analysis/knowledge-read.d.ts +45 -0
- package/dist/nexum-analysis/knowledge-read.d.ts.map +1 -0
- package/dist/nexum-analysis/knowledge-read.js +26 -0
- package/dist/nexum-analysis/knowledge-read.js.map +1 -0
- package/dist/openapi/openapi.json +18354 -17718
- package/dist/patches/access.d.ts +15 -0
- package/dist/patches/access.d.ts.map +1 -0
- package/dist/patches/access.js +27 -0
- package/dist/patches/access.js.map +1 -0
- package/dist/patches/engine.d.ts +67 -0
- package/dist/patches/engine.d.ts.map +1 -0
- package/dist/patches/engine.js +966 -0
- package/dist/patches/engine.js.map +1 -0
- package/dist/patches/guards.d.ts +23 -0
- package/dist/patches/guards.d.ts.map +1 -0
- package/dist/patches/guards.js +77 -0
- package/dist/patches/guards.js.map +1 -0
- package/dist/patches/legacy-rows.d.ts +56 -0
- package/dist/patches/legacy-rows.d.ts.map +1 -0
- package/dist/patches/legacy-rows.js +162 -0
- package/dist/patches/legacy-rows.js.map +1 -0
- package/dist/patches/ops.d.ts +24 -0
- package/dist/patches/ops.d.ts.map +1 -0
- package/dist/patches/ops.js +204 -0
- package/dist/patches/ops.js.map +1 -0
- package/dist/patches/parse.d.ts +5 -0
- package/dist/patches/parse.d.ts.map +1 -0
- package/dist/patches/parse.js +323 -0
- package/dist/patches/parse.js.map +1 -0
- package/dist/patches/paths.d.ts +38 -0
- package/dist/patches/paths.d.ts.map +1 -0
- package/dist/patches/paths.js +204 -0
- package/dist/patches/paths.js.map +1 -0
- package/dist/patches/service.d.ts +16 -0
- package/dist/patches/service.d.ts.map +1 -0
- package/dist/patches/service.js +128 -0
- package/dist/patches/service.js.map +1 -0
- package/dist/patches/store.d.ts +87 -0
- package/dist/patches/store.d.ts.map +1 -0
- package/dist/patches/store.js +27 -0
- package/dist/patches/store.js.map +1 -0
- package/dist/patches/types.d.ts +112 -0
- package/dist/patches/types.d.ts.map +1 -0
- package/dist/patches/types.js +5 -0
- package/dist/patches/types.js.map +1 -0
- package/dist/platform.d.ts +8 -0
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +98 -4
- package/dist/platform.js.map +1 -1
- package/dist/routes/anomaly.d.ts +5 -0
- package/dist/routes/anomaly.d.ts.map +1 -0
- package/dist/routes/anomaly.js +308 -0
- package/dist/routes/anomaly.js.map +1 -0
- package/dist/routes/data.d.ts.map +1 -1
- package/dist/routes/data.js +190 -202
- package/dist/routes/data.js.map +1 -1
- package/dist/routes/knowledge.d.ts.map +1 -1
- package/dist/routes/knowledge.js +6 -22
- package/dist/routes/knowledge.js.map +1 -1
- package/dist/routes/metadata.d.ts.map +1 -1
- package/dist/routes/metadata.js +28 -1
- package/dist/routes/metadata.js.map +1 -1
- package/dist/routes/patches.d.ts +7 -0
- package/dist/routes/patches.d.ts.map +1 -0
- package/dist/routes/patches.js +111 -0
- package/dist/routes/patches.js.map +1 -0
- package/dist/routes/subject-roots-backfill.d.ts +4 -0
- package/dist/routes/subject-roots-backfill.d.ts.map +1 -0
- package/dist/routes/subject-roots-backfill.js +15 -0
- package/dist/routes/subject-roots-backfill.js.map +1 -0
- package/dist/single-read-discriminator.d.ts +17 -0
- package/dist/single-read-discriminator.d.ts.map +1 -0
- package/dist/single-read-discriminator.js +67 -0
- package/dist/single-read-discriminator.js.map +1 -0
- package/dist/subject-roots-backfill.d.ts +24 -0
- package/dist/subject-roots-backfill.d.ts.map +1 -0
- package/dist/subject-roots-backfill.js +133 -0
- package/dist/subject-roots-backfill.js.map +1 -0
- package/dist/write-precondition.d.ts +5 -1
- package/dist/write-precondition.d.ts.map +1 -1
- package/dist/write-precondition.js +11 -3
- package/dist/write-precondition.js.map +1 -1
- package/dist/writes/content-write.d.ts +170 -0
- package/dist/writes/content-write.d.ts.map +1 -0
- package/dist/writes/content-write.js +569 -0
- package/dist/writes/content-write.js.map +1 -0
- package/dist/writes/effects.d.ts +13 -0
- package/dist/writes/effects.d.ts.map +1 -0
- package/dist/writes/effects.js +28 -0
- package/dist/writes/effects.js.map +1 -0
- package/dist/writes/error-shape.d.ts +11 -0
- package/dist/writes/error-shape.d.ts.map +1 -0
- package/dist/writes/error-shape.js +100 -0
- package/dist/writes/error-shape.js.map +1 -0
- package/dist/writes/receipt-store.d.ts +81 -0
- package/dist/writes/receipt-store.d.ts.map +1 -0
- package/dist/writes/receipt-store.js +171 -0
- package/dist/writes/receipt-store.js.map +1 -0
- package/dist/writes/worker.d.ts +9 -0
- package/dist/writes/worker.d.ts.map +1 -0
- package/dist/writes/worker.js +20 -0
- package/dist/writes/worker.js.map +1 -0
- package/openapi/openapi.json +18354 -17718
- package/package.json +4 -4
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
import { contentTypeOf, fieldsFor } from "./descriptors.js";
|
|
2
|
+
import { brief, collectDataLeaves, coversDeclared, finding, isIdentifierPath, isPlainObject, nonEmptyObject, readPath, valueMatchesType, } from "./values.js";
|
|
3
|
+
const MAX_FINDINGS = 25;
|
|
4
|
+
const RARE_PATH = 0.15;
|
|
5
|
+
const KIND_SUPPORT = 0.85;
|
|
6
|
+
const RARE_VALUE = 0.1;
|
|
7
|
+
const MODAL_VALUE = 0.6;
|
|
8
|
+
const MAX_DISTINCT = 8;
|
|
9
|
+
function wants(options, check) {
|
|
10
|
+
const checks = options?.checks ?? ["descriptor", "peer"];
|
|
11
|
+
return checks.includes(check);
|
|
12
|
+
}
|
|
13
|
+
function cap(findings) {
|
|
14
|
+
return findings.slice(0, MAX_FINDINGS);
|
|
15
|
+
}
|
|
16
|
+
export function normalizeRecords(records) {
|
|
17
|
+
return records.map((record, index) => ({
|
|
18
|
+
recordId: record.recordId?.trim() || `#${index + 1}`,
|
|
19
|
+
objectType: record.objectType,
|
|
20
|
+
contentType: record.contentType,
|
|
21
|
+
data: record.data === undefined ? {} : record.data,
|
|
22
|
+
...(record.analytics !== undefined ? { analytics: record.analytics } : {}),
|
|
23
|
+
...(record.enrichment !== undefined ? { enrichment: record.enrichment } : {}),
|
|
24
|
+
...(record.insights !== undefined ? { insights: record.insights } : {}),
|
|
25
|
+
}));
|
|
26
|
+
}
|
|
27
|
+
function recordRoot(record) {
|
|
28
|
+
return {
|
|
29
|
+
data: isPlainObject(record.data) ? record.data : {},
|
|
30
|
+
...(record.analytics !== undefined ? { analytics: record.analytics } : {}),
|
|
31
|
+
...(record.enrichment !== undefined ? { enrichment: record.enrichment } : {}),
|
|
32
|
+
...(record.insights !== undefined ? { insights: record.insights } : {}),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function descriptorFindings(record, descriptors) {
|
|
36
|
+
const objectType = descriptors.get(record.objectType);
|
|
37
|
+
if (!objectType) {
|
|
38
|
+
return [
|
|
39
|
+
finding("descriptor", "UNKNOWN_OBJECT_TYPE", `Record ${record.recordId} uses object type "${record.objectType}", which is not in the installed descriptors.`, { objectType: record.objectType, actual: record.objectType }),
|
|
40
|
+
];
|
|
41
|
+
}
|
|
42
|
+
const contentType = contentTypeOf(objectType, record.contentType);
|
|
43
|
+
if (!contentType) {
|
|
44
|
+
return [
|
|
45
|
+
finding("descriptor", "UNKNOWN_CONTENT_TYPE", `Record ${record.recordId} uses content type "${record.contentType}", which is not declared on object type "${objectType.id}".`, {
|
|
46
|
+
objectType: objectType.id,
|
|
47
|
+
contentType: record.contentType,
|
|
48
|
+
expected: objectType.contentTypes.map((ct) => ct.id),
|
|
49
|
+
actual: record.contentType,
|
|
50
|
+
}),
|
|
51
|
+
];
|
|
52
|
+
}
|
|
53
|
+
const findings = [];
|
|
54
|
+
if (!isPlainObject(record.data)) {
|
|
55
|
+
findings.push(finding("descriptor", "DATA_SHAPE", `Record ${record.recordId} data is not an object.`, { path: "data", objectType: objectType.id, contentType: contentType.id, actual: brief(record.data) }));
|
|
56
|
+
}
|
|
57
|
+
if (contentType.allowSnapshotBuckets === undefined) {
|
|
58
|
+
findings.push(finding("descriptor", "DESCRIPTOR_MISSING", `Content type "${contentType.id}" on "${objectType.id}" has no allowSnapshotBuckets descriptor.`, { objectType: objectType.id, contentType: contentType.id }));
|
|
59
|
+
}
|
|
60
|
+
else if (contentType.allowSnapshotBuckets === false) {
|
|
61
|
+
for (const bucket of ["analytics", "enrichment", "insights"]) {
|
|
62
|
+
if (!nonEmptyObject(record[bucket]))
|
|
63
|
+
continue;
|
|
64
|
+
findings.push(finding("descriptor", "SNAPSHOT_BUCKET", `Record ${record.recordId} has ${bucket}, and content type "${contentType.id}" does not allow snapshot buckets.`, { path: bucket, objectType: objectType.id, contentType: contentType.id }));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const disc = contentType.discriminator;
|
|
68
|
+
if (disc?.path && disc.required && !disc.defaultValue) {
|
|
69
|
+
const value = readPath(recordRoot(record), disc.path);
|
|
70
|
+
if (value === undefined || value === null) {
|
|
71
|
+
findings.push(finding("descriptor", "DISCRIMINATOR_MISSING", `Record ${record.recordId} is missing required discriminator ${disc.path}.`, { path: disc.path, objectType: objectType.id, contentType: contentType.id }));
|
|
72
|
+
}
|
|
73
|
+
else if (typeof value !== "string" || !value.trim()) {
|
|
74
|
+
findings.push(finding("descriptor", "DISCRIMINATOR_TYPE", `Discriminator ${disc.path} on record ${record.recordId} must be a non-empty string.`, { path: disc.path, objectType: objectType.id, contentType: contentType.id, actual: brief(value) }));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const fields = fieldsFor(objectType, contentType.id);
|
|
78
|
+
const root = recordRoot(record);
|
|
79
|
+
const gateOpen = (field) => !field.when || readPath(root, field.when.path) === field.when.equals;
|
|
80
|
+
const specificity = (field) => (field.contentType ? 1 : 0) + (field.when ? 1 : 0);
|
|
81
|
+
for (const field of fields) {
|
|
82
|
+
if (!gateOpen(field))
|
|
83
|
+
continue;
|
|
84
|
+
// A more specific descriptor for the same path takes precedence over a general one.
|
|
85
|
+
const own = specificity(field);
|
|
86
|
+
if (fields.some((other) => other !== field && other.path === field.path && gateOpen(other) && specificity(other) > own)) {
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
const value = readPath(root, field.path);
|
|
90
|
+
if (value === undefined || value === null)
|
|
91
|
+
continue;
|
|
92
|
+
if (field.enum) {
|
|
93
|
+
if (field.enum.length === 0 || typeof value !== "string" || value === "" || !field.enum.includes(value)) {
|
|
94
|
+
findings.push(finding("descriptor", "ENUM", `Field ${field.path} on record ${record.recordId} is outside its closed vocabulary.`, {
|
|
95
|
+
path: field.path,
|
|
96
|
+
objectType: objectType.id,
|
|
97
|
+
contentType: contentType.id,
|
|
98
|
+
expected: field.enum,
|
|
99
|
+
actual: brief(value),
|
|
100
|
+
}));
|
|
101
|
+
}
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
if (!valueMatchesType(field.valueType, value)) {
|
|
105
|
+
findings.push(finding("descriptor", "VALUE_TYPE", `Field ${field.path} on record ${record.recordId} is not a ${field.valueType}.`, {
|
|
106
|
+
path: field.path,
|
|
107
|
+
objectType: objectType.id,
|
|
108
|
+
contentType: contentType.id,
|
|
109
|
+
expected: field.valueType,
|
|
110
|
+
actual: brief(value),
|
|
111
|
+
}));
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
if (field.refersTo && !refersToOk(value)) {
|
|
115
|
+
findings.push(finding("descriptor", "REFERS_TO", `Field ${field.path} on record ${record.recordId} should identify a ${field.refersTo.objectType} record.`, {
|
|
116
|
+
path: field.path,
|
|
117
|
+
objectType: objectType.id,
|
|
118
|
+
contentType: contentType.id,
|
|
119
|
+
expected: field.refersTo.objectType,
|
|
120
|
+
actual: brief(value),
|
|
121
|
+
}));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
const covered = fields.map((field) => field.path);
|
|
125
|
+
if (disc?.path)
|
|
126
|
+
covered.push(disc.path);
|
|
127
|
+
if (fields.length > 0 && isPlainObject(record.data)) {
|
|
128
|
+
for (const leaf of collectDataLeaves(record.data)) {
|
|
129
|
+
if (leaf.path === "data")
|
|
130
|
+
continue;
|
|
131
|
+
if (covered.some((path) => coversDeclared(path, leaf.path)))
|
|
132
|
+
continue;
|
|
133
|
+
findings.push(finding("descriptor", "UNDECLARED_PATH", `Record ${record.recordId} has ${leaf.path}, which is not in the field descriptors for ${objectType.id}/${contentType.id}.`, { path: leaf.path, objectType: objectType.id, contentType: contentType.id }));
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return findings;
|
|
137
|
+
}
|
|
138
|
+
function refersToOk(value) {
|
|
139
|
+
if (typeof value === "string")
|
|
140
|
+
return value.trim().length > 0;
|
|
141
|
+
if (!Array.isArray(value) || value.length === 0)
|
|
142
|
+
return false;
|
|
143
|
+
return value.every((item) => typeof item === "string" && item.trim().length > 0);
|
|
144
|
+
}
|
|
145
|
+
function indexLeaves(leaves) {
|
|
146
|
+
const map = new Map();
|
|
147
|
+
for (const leaf of leaves) {
|
|
148
|
+
if (!map.has(leaf.path))
|
|
149
|
+
map.set(leaf.path, leaf);
|
|
150
|
+
}
|
|
151
|
+
return map;
|
|
152
|
+
}
|
|
153
|
+
function peerFindings(group, minCohort, presenceSupport) {
|
|
154
|
+
const empty = group.map(() => []);
|
|
155
|
+
if (group.length < minCohort)
|
|
156
|
+
return empty;
|
|
157
|
+
const leaves = group.map((record) => isPlainObject(record.data) ? indexLeaves(collectDataLeaves(record.data)) : new Map());
|
|
158
|
+
const stats = new Map();
|
|
159
|
+
for (const map of leaves) {
|
|
160
|
+
for (const [path, leaf] of map) {
|
|
161
|
+
if (path === "data")
|
|
162
|
+
continue;
|
|
163
|
+
let stat = stats.get(path);
|
|
164
|
+
if (!stat) {
|
|
165
|
+
stat = { present: 0, kinds: new Map(), values: new Map(), valuesCapped: false };
|
|
166
|
+
stats.set(path, stat);
|
|
167
|
+
}
|
|
168
|
+
stat.present += 1;
|
|
169
|
+
stat.kinds.set(leaf.kind, (stat.kinds.get(leaf.kind) ?? 0) + 1);
|
|
170
|
+
if (leaf.scalar !== undefined && !isIdentifierPath(path)) {
|
|
171
|
+
if (stat.values.size < 32 || stat.values.has(leaf.scalar)) {
|
|
172
|
+
stat.values.set(leaf.scalar, (stat.values.get(leaf.scalar) ?? 0) + 1);
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
stat.valuesCapped = true;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
const n = group.length;
|
|
181
|
+
return leaves.map((map, index) => {
|
|
182
|
+
const findings = [];
|
|
183
|
+
const record = group[index];
|
|
184
|
+
for (const [path, stat] of stats) {
|
|
185
|
+
const support = stat.present / n;
|
|
186
|
+
const leaf = map.get(path);
|
|
187
|
+
if (!leaf && support >= presenceSupport) {
|
|
188
|
+
findings.push(finding("peer", "MISSING_COMMON_FIELD", `Record ${record.recordId} is missing ${path}, which is present on ${stat.present} of ${n} ${record.objectType}/${record.contentType} records.`, { path, objectType: record.objectType, contentType: record.contentType, expected: path }));
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
if (leaf && support <= RARE_PATH) {
|
|
192
|
+
findings.push(finding("peer", "EXTRA_RARE_FIELD", `Record ${record.recordId} has ${path}, which appears on ${stat.present} of ${n} ${record.objectType}/${record.contentType} records.`, { path, objectType: record.objectType, contentType: record.contentType, actual: path }));
|
|
193
|
+
}
|
|
194
|
+
if (!leaf || leaf.kind === "null")
|
|
195
|
+
continue;
|
|
196
|
+
let primary = "";
|
|
197
|
+
let primaryCount = 0;
|
|
198
|
+
for (const [kind, count] of stat.kinds) {
|
|
199
|
+
if (kind === "null")
|
|
200
|
+
continue;
|
|
201
|
+
if (count > primaryCount) {
|
|
202
|
+
primary = kind;
|
|
203
|
+
primaryCount = count;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
const presentNonNull = stat.present - (stat.kinds.get("null") ?? 0);
|
|
207
|
+
if (primary && presentNonNull > 0 && primaryCount / presentNonNull >= KIND_SUPPORT && leaf.kind !== primary) {
|
|
208
|
+
findings.push(finding("peer", "VALUE_KIND", `Record ${record.recordId} has a ${leaf.kind} at ${path}; ${primaryCount} of ${presentNonNull} populated values are ${primary}.`, {
|
|
209
|
+
path,
|
|
210
|
+
objectType: record.objectType,
|
|
211
|
+
contentType: record.contentType,
|
|
212
|
+
expected: primary,
|
|
213
|
+
actual: leaf.kind,
|
|
214
|
+
}));
|
|
215
|
+
}
|
|
216
|
+
if (leaf.scalar !== undefined &&
|
|
217
|
+
!stat.valuesCapped &&
|
|
218
|
+
!isIdentifierPath(path) &&
|
|
219
|
+
stat.values.size > 0 &&
|
|
220
|
+
stat.values.size <= MAX_DISTINCT) {
|
|
221
|
+
let modal = "";
|
|
222
|
+
let modalCount = 0;
|
|
223
|
+
for (const [value, count] of stat.values) {
|
|
224
|
+
if (count > modalCount) {
|
|
225
|
+
modal = value;
|
|
226
|
+
modalCount = count;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
const mine = stat.values.get(leaf.scalar) ?? 0;
|
|
230
|
+
if (modal &&
|
|
231
|
+
stat.present > 0 &&
|
|
232
|
+
modalCount / stat.present >= MODAL_VALUE &&
|
|
233
|
+
mine / stat.present <= RARE_VALUE) {
|
|
234
|
+
findings.push(finding("peer", "RARE_VALUE", `Record ${record.recordId} has an uncommon value at ${path}. ${modalCount} of ${stat.present} records use "${modal}".`, {
|
|
235
|
+
path,
|
|
236
|
+
objectType: record.objectType,
|
|
237
|
+
contentType: record.contentType,
|
|
238
|
+
expected: modal,
|
|
239
|
+
actual: leaf.scalar,
|
|
240
|
+
}));
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return findings;
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
function missingRequired(records, descriptors) {
|
|
248
|
+
const bySubject = new Map();
|
|
249
|
+
for (const record of records) {
|
|
250
|
+
const key = `${record.objectType}\0${record.recordId}`;
|
|
251
|
+
let slot = bySubject.get(key);
|
|
252
|
+
if (!slot) {
|
|
253
|
+
slot = { objectType: record.objectType, recordId: record.recordId, contentTypes: new Set() };
|
|
254
|
+
bySubject.set(key, slot);
|
|
255
|
+
}
|
|
256
|
+
slot.contentTypes.add(record.contentType);
|
|
257
|
+
}
|
|
258
|
+
const items = [];
|
|
259
|
+
for (const slot of bySubject.values()) {
|
|
260
|
+
const objectType = descriptors.find((ot) => ot.id === slot.objectType);
|
|
261
|
+
if (!objectType)
|
|
262
|
+
continue;
|
|
263
|
+
for (const contentType of objectType.contentTypes) {
|
|
264
|
+
if (!contentType.required || slot.contentTypes.has(contentType.id))
|
|
265
|
+
continue;
|
|
266
|
+
items.push({
|
|
267
|
+
recordId: slot.recordId,
|
|
268
|
+
objectType: objectType.id,
|
|
269
|
+
contentType: contentType.id,
|
|
270
|
+
findings: [
|
|
271
|
+
finding("descriptor", "MISSING_REQUIRED_CONTENT_TYPE", `Subject ${slot.recordId} has no "${contentType.id}" content, which is required on object type "${objectType.id}".`, {
|
|
272
|
+
objectType: objectType.id,
|
|
273
|
+
contentType: contentType.id,
|
|
274
|
+
...(contentType.requiredReason ? { expected: contentType.requiredReason } : {}),
|
|
275
|
+
}),
|
|
276
|
+
],
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return items;
|
|
281
|
+
}
|
|
282
|
+
export function classifyRecords(descriptors, records, options) {
|
|
283
|
+
const byId = new Map();
|
|
284
|
+
for (const objectType of descriptors) {
|
|
285
|
+
if (!byId.has(objectType.id))
|
|
286
|
+
byId.set(objectType.id, objectType);
|
|
287
|
+
}
|
|
288
|
+
const normalized = normalizeRecords(records);
|
|
289
|
+
const descriptorOn = wants(options, "descriptor");
|
|
290
|
+
const peerOn = wants(options, "peer");
|
|
291
|
+
const minCohort = options?.minCohort ?? 4;
|
|
292
|
+
const presenceSupport = options?.presenceSupport ?? 0.8;
|
|
293
|
+
const descriptor = descriptorOn
|
|
294
|
+
? normalized.map((record) => descriptorFindings(record, byId))
|
|
295
|
+
: normalized.map(() => []);
|
|
296
|
+
const peer = normalized.map(() => []);
|
|
297
|
+
if (peerOn) {
|
|
298
|
+
const groups = new Map();
|
|
299
|
+
normalized.forEach((record, index) => {
|
|
300
|
+
const key = `${record.objectType}\0${record.contentType}`;
|
|
301
|
+
const bucket = groups.get(key) ?? [];
|
|
302
|
+
bucket.push(index);
|
|
303
|
+
groups.set(key, bucket);
|
|
304
|
+
});
|
|
305
|
+
for (const indexes of groups.values()) {
|
|
306
|
+
const group = indexes.map((index) => normalized[index]);
|
|
307
|
+
const found = peerFindings(group, minCohort, presenceSupport);
|
|
308
|
+
found.forEach((list, offset) => {
|
|
309
|
+
peer[indexes[offset]] = list;
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return normalized.map((record, index) => ({
|
|
314
|
+
record,
|
|
315
|
+
descriptor: descriptor[index],
|
|
316
|
+
peer: peer[index],
|
|
317
|
+
}));
|
|
318
|
+
}
|
|
319
|
+
function toItems(rows, include) {
|
|
320
|
+
const items = [];
|
|
321
|
+
for (const row of rows) {
|
|
322
|
+
const findings = include === "descriptor" ? row.descriptor : include === "peer" ? row.peer : [...row.descriptor, ...row.peer];
|
|
323
|
+
if (findings.length === 0)
|
|
324
|
+
continue;
|
|
325
|
+
items.push({
|
|
326
|
+
recordId: row.record.recordId,
|
|
327
|
+
objectType: row.record.objectType,
|
|
328
|
+
contentType: row.record.contentType,
|
|
329
|
+
findings: cap(findings),
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
return items;
|
|
333
|
+
}
|
|
334
|
+
export function detectRecordAnomalies(descriptors, records, options) {
|
|
335
|
+
const rows = classifyRecords(descriptors, records, options);
|
|
336
|
+
const items = toItems(rows, "both");
|
|
337
|
+
if (wants(options, "descriptor") && options?.checkRequiredContentTypes && !options.truncated) {
|
|
338
|
+
const seen = new Set(items.map((item) => `${item.objectType}\0${item.recordId}\0${item.contentType}`));
|
|
339
|
+
for (const missing of missingRequired(rows.map((row) => row.record), descriptors)) {
|
|
340
|
+
const key = `${missing.objectType}\0${missing.recordId}\0${missing.contentType}`;
|
|
341
|
+
if (seen.has(key))
|
|
342
|
+
continue;
|
|
343
|
+
items.push(missing);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
items.sort((a, b) => b.findings.length - a.findings.length ||
|
|
347
|
+
a.objectType.localeCompare(b.objectType) ||
|
|
348
|
+
a.contentType.localeCompare(b.contentType) ||
|
|
349
|
+
a.recordId.localeCompare(b.recordId));
|
|
350
|
+
const limit = options?.limit ?? 100;
|
|
351
|
+
return {
|
|
352
|
+
scannedRecords: records.length,
|
|
353
|
+
truncated: Boolean(options?.truncated),
|
|
354
|
+
limited: items.length > limit,
|
|
355
|
+
anomalous: items.length,
|
|
356
|
+
items: items.slice(0, limit),
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
export function driftBy(rows, keyOf) {
|
|
360
|
+
const map = new Map();
|
|
361
|
+
for (const row of rows) {
|
|
362
|
+
const key = keyOf(row.record);
|
|
363
|
+
let bucket = map.get(key);
|
|
364
|
+
if (!bucket) {
|
|
365
|
+
bucket = {
|
|
366
|
+
scanned: 0,
|
|
367
|
+
descriptorAnomalies: 0,
|
|
368
|
+
peerAnomalies: 0,
|
|
369
|
+
descriptorFindings: [],
|
|
370
|
+
peerFindings: [],
|
|
371
|
+
};
|
|
372
|
+
map.set(key, bucket);
|
|
373
|
+
}
|
|
374
|
+
bucket.scanned += 1;
|
|
375
|
+
if (row.descriptor.length > 0)
|
|
376
|
+
bucket.descriptorAnomalies += 1;
|
|
377
|
+
if (row.peer.length > 0)
|
|
378
|
+
bucket.peerAnomalies += 1;
|
|
379
|
+
bucket.descriptorFindings.push(...row.descriptor);
|
|
380
|
+
bucket.peerFindings.push(...row.peer);
|
|
381
|
+
}
|
|
382
|
+
return map;
|
|
383
|
+
}
|
|
384
|
+
//# sourceMappingURL=records.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"records.js","sourceRoot":"","sources":["../../src/anomaly/records.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read-only anomaly tools. Nothing here installs or rewrites metadata or records.
|
|
3
|
+
*/
|
|
4
|
+
export type AnomalyCheck = "descriptor" | "peer";
|
|
5
|
+
export type AnomalyFinding = {
|
|
6
|
+
kind: AnomalyCheck;
|
|
7
|
+
code: string;
|
|
8
|
+
message: string;
|
|
9
|
+
path?: string;
|
|
10
|
+
objectType?: string;
|
|
11
|
+
contentType?: string;
|
|
12
|
+
expected?: unknown;
|
|
13
|
+
actual?: unknown;
|
|
14
|
+
};
|
|
15
|
+
export type ContentTypeDescriptor = {
|
|
16
|
+
id: string;
|
|
17
|
+
/** Absent when the installed declaration has no boolean profile flag. */
|
|
18
|
+
allowSnapshotBuckets?: boolean;
|
|
19
|
+
required: boolean;
|
|
20
|
+
requiredReason?: string;
|
|
21
|
+
leading: boolean;
|
|
22
|
+
discriminator?: {
|
|
23
|
+
path?: string;
|
|
24
|
+
required: boolean;
|
|
25
|
+
defaultValue?: string;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
export type FieldDescriptor = {
|
|
29
|
+
path: string;
|
|
30
|
+
valueType: string;
|
|
31
|
+
contentType?: string;
|
|
32
|
+
enum?: string[];
|
|
33
|
+
/** The field applies only to records whose value at `when.path` equals `when.equals`. */
|
|
34
|
+
when?: {
|
|
35
|
+
path: string;
|
|
36
|
+
equals: string;
|
|
37
|
+
};
|
|
38
|
+
refersTo?: {
|
|
39
|
+
objectType: string;
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
export type ObjectTypeDescriptor = {
|
|
43
|
+
id: string;
|
|
44
|
+
name: string;
|
|
45
|
+
dataCategory: string;
|
|
46
|
+
contentTypes: ContentTypeDescriptor[];
|
|
47
|
+
fields: FieldDescriptor[];
|
|
48
|
+
};
|
|
49
|
+
/** A stored record, or a batch item posted to the tool. */
|
|
50
|
+
export type AnomalyRecord = {
|
|
51
|
+
recordId?: string;
|
|
52
|
+
objectType: string;
|
|
53
|
+
contentType: string;
|
|
54
|
+
data?: unknown;
|
|
55
|
+
analytics?: unknown;
|
|
56
|
+
enrichment?: unknown;
|
|
57
|
+
insights?: unknown;
|
|
58
|
+
};
|
|
59
|
+
export type RecordAnomalyItem = {
|
|
60
|
+
recordId: string;
|
|
61
|
+
objectType: string;
|
|
62
|
+
contentType: string;
|
|
63
|
+
findings: AnomalyFinding[];
|
|
64
|
+
};
|
|
65
|
+
export type ObjectTypeAnomalyItem = {
|
|
66
|
+
objectType: string;
|
|
67
|
+
name: string;
|
|
68
|
+
dataCategory: string;
|
|
69
|
+
findings: AnomalyFinding[];
|
|
70
|
+
};
|
|
71
|
+
export type ContentTypeAnomalyItem = {
|
|
72
|
+
contentType: string;
|
|
73
|
+
objectTypes: string[];
|
|
74
|
+
findings: AnomalyFinding[];
|
|
75
|
+
};
|
|
76
|
+
export type AnomalyDetectOptions = {
|
|
77
|
+
checks?: AnomalyCheck[];
|
|
78
|
+
/** Peer and drift findings need at least this many records in the cohort. */
|
|
79
|
+
minCohort?: number;
|
|
80
|
+
/** A path present in at least this fraction of the cohort is common. */
|
|
81
|
+
presenceSupport?: number;
|
|
82
|
+
/** Max anomalous items returned. */
|
|
83
|
+
limit?: number;
|
|
84
|
+
/**
|
|
85
|
+
* When true, a subject that was seen without a required content type is reported.
|
|
86
|
+
* Store scans set this only after a complete pass.
|
|
87
|
+
*/
|
|
88
|
+
checkRequiredContentTypes?: boolean;
|
|
89
|
+
/** The store scan stopped before every matching record was read. */
|
|
90
|
+
truncated?: boolean;
|
|
91
|
+
};
|
|
92
|
+
export type AnomalyReport<T> = {
|
|
93
|
+
scannedRecords: number | null;
|
|
94
|
+
truncated: boolean;
|
|
95
|
+
limited: boolean;
|
|
96
|
+
/** Anomalous rows found before the response limit. */
|
|
97
|
+
anomalous: number;
|
|
98
|
+
items: T[];
|
|
99
|
+
};
|
|
100
|
+
export declare const ANOMALY_TOOLS: readonly [{
|
|
101
|
+
readonly name: "records";
|
|
102
|
+
readonly method: "POST";
|
|
103
|
+
readonly path: "/api/intelligence/anomalies/records";
|
|
104
|
+
readonly description: "Records that do not match their object-type and content-type descriptors, and records that differ from the common records of the same object type and content type.";
|
|
105
|
+
}, {
|
|
106
|
+
readonly name: "object-types";
|
|
107
|
+
readonly method: "POST";
|
|
108
|
+
readonly path: "/api/intelligence/anomalies/object-types";
|
|
109
|
+
readonly description: "Object types whose declarations disagree with descriptor rules or with the records stored on them, and object types that differ from the common object types.";
|
|
110
|
+
}, {
|
|
111
|
+
readonly name: "content-types";
|
|
112
|
+
readonly method: "POST";
|
|
113
|
+
readonly path: "/api/intelligence/anomalies/content-types";
|
|
114
|
+
readonly description: "Content types whose declarations disagree across object types or with stored records, and content types that differ from the common content types.";
|
|
115
|
+
}];
|
|
116
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/anomaly/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read-only anomaly tools. Nothing here installs or rewrites metadata or records.
|
|
3
|
+
*/
|
|
4
|
+
export const ANOMALY_TOOLS = [
|
|
5
|
+
{
|
|
6
|
+
name: "records",
|
|
7
|
+
method: "POST",
|
|
8
|
+
path: "/api/intelligence/anomalies/records",
|
|
9
|
+
description: "Records that do not match their object-type and content-type descriptors, and records that differ from the common records of the same object type and content type.",
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
name: "object-types",
|
|
13
|
+
method: "POST",
|
|
14
|
+
path: "/api/intelligence/anomalies/object-types",
|
|
15
|
+
description: "Object types whose declarations disagree with descriptor rules or with the records stored on them, and object types that differ from the common object types.",
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
name: "content-types",
|
|
19
|
+
method: "POST",
|
|
20
|
+
path: "/api/intelligence/anomalies/content-types",
|
|
21
|
+
description: "Content types whose declarations disagree across object types or with stored records, and content types that differ from the common content types.",
|
|
22
|
+
},
|
|
23
|
+
];
|
|
24
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/anomaly/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAwGH,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B;QACE,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,qCAAqC;QAC3C,WAAW,EACT,qKAAqK;KACxK;IACD;QACE,IAAI,EAAE,cAAc;QACpB,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,0CAA0C;QAChD,WAAW,EACT,+JAA+J;KAClK;IACD;QACE,IAAI,EAAE,eAAe;QACrB,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,2CAA2C;QACjD,WAAW,EACT,oJAAoJ;KACvJ;CACO,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { AnomalyFinding, AnomalyCheck } from "./types.js";
|
|
2
|
+
export declare const DATA_CATEGORIES: Set<string>;
|
|
3
|
+
export declare function finding(kind: AnomalyCheck, code: string, message: string, extra?: Partial<Omit<AnomalyFinding, "kind" | "code" | "message">>): AnomalyFinding;
|
|
4
|
+
export declare function brief(value: unknown): unknown;
|
|
5
|
+
export declare function readPath(root: unknown, path: string): unknown;
|
|
6
|
+
export declare function isPlainObject(value: unknown): value is Record<string, unknown>;
|
|
7
|
+
export type ObservedKind = "string" | "number" | "boolean" | "object" | "array" | "null" | "date" | "unknown";
|
|
8
|
+
export type LeafObservation = {
|
|
9
|
+
path: string;
|
|
10
|
+
kind: ObservedKind;
|
|
11
|
+
scalar?: string;
|
|
12
|
+
};
|
|
13
|
+
export declare function observedKind(value: unknown): ObservedKind;
|
|
14
|
+
/** Leaf paths under `data`. Objects contribute their children; empty objects and arrays are leaves. */
|
|
15
|
+
export declare function collectDataLeaves(data: unknown): LeafObservation[];
|
|
16
|
+
export declare function isIdentifierPath(path: string): boolean;
|
|
17
|
+
export declare function valueMatchesType(valueType: string, value: unknown): boolean;
|
|
18
|
+
export declare function coversDeclared(declared: string, observed: string): boolean;
|
|
19
|
+
export declare function nonEmptyObject(value: unknown): boolean;
|
|
20
|
+
export declare function majority(values: string[]): {
|
|
21
|
+
value: string;
|
|
22
|
+
share: number;
|
|
23
|
+
} | null;
|
|
24
|
+
export declare function median(values: number[]): number;
|
|
25
|
+
/** Far from the other values: empty while the rest are populated, or several times the median. */
|
|
26
|
+
export declare function isCountOutlier(value: number, others: number[]): boolean;
|
|
27
|
+
export declare function topCodes(findings: AnomalyFinding[], take?: number): Array<{
|
|
28
|
+
code: string;
|
|
29
|
+
count: number;
|
|
30
|
+
}>;
|
|
31
|
+
//# sourceMappingURL=values.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"values.d.ts","sourceRoot":"","sources":["../../src/anomaly/values.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/D,eAAO,MAAM,eAAe,aAA4C,CAAC;AAIzE,wBAAgB,OAAO,CACrB,IAAI,EAAE,YAAY,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,CAAC,GACjE,cAAc,CAEhB;AAED,wBAAgB,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAM7C;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAQ7D;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE9E;AAED,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AAE9G,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,YAAY,CAczD;AAKD,uGAAuG;AACvG,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,eAAe,EAAE,CAIlE;AAiCD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAItD;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAyB3E;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE1E;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEtD;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAalF;AAED,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAI/C;AAED,kGAAkG;AAClG,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAKvE;AAED,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,cAAc,EAAE,EAAE,IAAI,SAAI,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAOrG"}
|