@gate-forge/core 0.12.0 → 0.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/dist/baselines/adoption.d.ts +70 -3
- package/dist/baselines/adoption.d.ts.map +1 -1
- package/dist/baselines/adoption.js +144 -5
- package/dist/baselines/adoption.js.map +1 -1
- package/dist/classifier/classify.d.ts +3 -0
- package/dist/classifier/classify.d.ts.map +1 -1
- package/dist/classifier/classify.js +39 -18
- package/dist/classifier/classify.js.map +1 -1
- package/dist/classifier/schema.d.ts +1 -0
- package/dist/classifier/schema.d.ts.map +1 -1
- package/dist/config/index.d.ts +46 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +51 -0
- package/dist/config/index.js.map +1 -1
- package/dist/graph/schema.d.ts +2 -0
- package/dist/graph/schema.d.ts.map +1 -1
- package/dist/index.d.ts +10 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/schemas/adoption.d.ts +43 -0
- package/dist/schemas/adoption.d.ts.map +1 -1
- package/dist/schemas/adoption.js +102 -0
- package/dist/schemas/adoption.js.map +1 -1
- package/dist/schemas/classification.d.ts +7 -8
- package/dist/schemas/classification.d.ts.map +1 -1
- package/dist/schemas/classification.js +15 -20
- package/dist/schemas/classification.js.map +1 -1
- package/dist/verdict/cause.d.ts.map +1 -1
- package/dist/verdict/cause.js +30 -6
- package/dist/verdict/cause.js.map +1 -1
- package/dist/verdict/evaluate.d.ts.map +1 -1
- package/dist/verdict/evaluate.js +209 -44
- package/dist/verdict/evaluate.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type AdoptionRecord } from '../schemas/adoption.js';
|
|
1
|
+
import { type AdoptionFamily, type AdoptionRecord } from '../schemas/adoption.js';
|
|
2
2
|
/** The adoption record's fixed file name, beside the baseline document. */
|
|
3
3
|
export declare const ADOPTION_RECORD_FILENAME = "adoption.json";
|
|
4
4
|
/**
|
|
@@ -21,12 +21,21 @@ export declare function loadAdoptionRecord(path: string): AdoptionRecord | null;
|
|
|
21
21
|
* needed. Serialized sorted 2-space JSON with a trailing newline
|
|
22
22
|
* (reviewable in diffs, like the baseline document).
|
|
23
23
|
*
|
|
24
|
+
* The receipt is the ONE sanction record a repository cannot regenerate,
|
|
25
|
+
* so the write is validated BEFORE any filesystem mutation and then
|
|
26
|
+
* ATOMIC: the serialized bytes go to a same-directory temporary file and
|
|
27
|
+
* `rename` over the destination. A crash or a failed write can never
|
|
28
|
+
* leave the receipt truncated or half-written — the previous receipt
|
|
29
|
+
* stays intact and in force, and the temporary file is removed on any
|
|
30
|
+
* failure (cleanup errors never mask the write error).
|
|
31
|
+
*
|
|
24
32
|
* Args:
|
|
25
33
|
* path: destination file path.
|
|
26
|
-
* record: the
|
|
34
|
+
* record: the adoption record to persist.
|
|
27
35
|
*
|
|
28
36
|
* Throws:
|
|
29
|
-
* GateforgeBaselineError: when the
|
|
37
|
+
* GateforgeBaselineError: when the record fails validation or the file
|
|
38
|
+
* cannot be written (the previous receipt, if any, is untouched).
|
|
30
39
|
*/
|
|
31
40
|
export declare function writeAdoptionRecord(path: string, record: AdoptionRecord): void;
|
|
32
41
|
/**
|
|
@@ -73,4 +82,62 @@ export declare function adoptClassificationBlocked(resourceIds: readonly string[
|
|
|
73
82
|
* non-strict-subset update (naming the added ids).
|
|
74
83
|
*/
|
|
75
84
|
export declare function shrinkClassificationBlocked(current: AdoptionRecord, resourceIds: readonly string[]): AdoptionRecord;
|
|
85
|
+
/**
|
|
86
|
+
* Builds one family's permanent marker (0.13): the named, dated,
|
|
87
|
+
* commit-referenced slice a post-adoption migration records in the
|
|
88
|
+
* EXISTING receipt. `fingerprintsById` must already contain EVERY
|
|
89
|
+
* initial family obligation id — proven obligations included — keyed by
|
|
90
|
+
* obligation id with its pin-#2 fingerprint; `forgiven` names the
|
|
91
|
+
* sanctioned subset (only what was missing/unproven). Input order is
|
|
92
|
+
* irrelevant: the marker is normalized to sorted keys and a sorted,
|
|
93
|
+
* duplicate-free `forgiven` list, so the receipt bytes are deterministic
|
|
94
|
+
* (and with them the trusted-policy digest that binds the marker).
|
|
95
|
+
*
|
|
96
|
+
* Args:
|
|
97
|
+
* input.adoptedAt: the family adoption instant (run's injected clock).
|
|
98
|
+
* input.gitSha: HEAD sha of the adopting commit, or null outside git.
|
|
99
|
+
* input.fingerprintsById: every initial family obligation id → fingerprint.
|
|
100
|
+
* input.forgiven: the sanctioned (missing/unproven) subset to forgive.
|
|
101
|
+
*
|
|
102
|
+
* Returns:
|
|
103
|
+
* AdoptionFamily: the validated marker for the receipt's `families` map.
|
|
104
|
+
*
|
|
105
|
+
* Throws:
|
|
106
|
+
* GateforgeBaselineError: when a forgiven fingerprint is not one of the
|
|
107
|
+
* recorded ones, a fingerprint is malformed, or an id is empty (fail
|
|
108
|
+
* closed — a marker that forgives beyond its own record is never built).
|
|
109
|
+
*/
|
|
110
|
+
export declare function adoptFamily(input: {
|
|
111
|
+
adoptedAt: string;
|
|
112
|
+
gitSha: string | null;
|
|
113
|
+
fingerprintsById: Record<string, string>;
|
|
114
|
+
forgiven: readonly string[];
|
|
115
|
+
}): AdoptionFamily;
|
|
116
|
+
/**
|
|
117
|
+
* A family's ONLY mutation after adoption (the shrink path, mirroring
|
|
118
|
+
* `updateBaseline`'s GF-07/08 semantics and the classification set's):
|
|
119
|
+
* replaces the named family's `forgiven` list with the given
|
|
120
|
+
* fingerprints, which must be a STRICT SUBSET of the current ones —
|
|
121
|
+
* every fingerprint kept must exist today AND at least one must be
|
|
122
|
+
* removed. The marker itself is retained untouched (adoptedAt, gitSha,
|
|
123
|
+
* every recorded fingerprint), so a repeat migration can never re-arm
|
|
124
|
+
* and a resolved debt can never re-enter: the sanctioned set can only
|
|
125
|
+
* shrink.
|
|
126
|
+
*
|
|
127
|
+
* Args:
|
|
128
|
+
* current: the adopted record on disk.
|
|
129
|
+
* name: the family to shrink (only `pages` exists today).
|
|
130
|
+
* fingerprints: the fingerprints to KEEP (duplicates are an error, as
|
|
131
|
+
* in `updateBaseline`; an empty list keeps none).
|
|
132
|
+
*
|
|
133
|
+
* Returns:
|
|
134
|
+
* AdoptionRecord: the next record — identical to `current` except for
|
|
135
|
+
* the named family's shrunk `forgiven` list.
|
|
136
|
+
*
|
|
137
|
+
* Throws:
|
|
138
|
+
* GateforgeBaselineError: when the record carries no such family
|
|
139
|
+
* marker, on duplicate input, on schema-invalid fingerprints, or on a
|
|
140
|
+
* non-strict-subset update (naming the unknown or added fingerprints).
|
|
141
|
+
*/
|
|
142
|
+
export declare function shrinkFamilyForgiven(current: AdoptionRecord, name: string, fingerprints: readonly string[]): AdoptionRecord;
|
|
76
143
|
//# sourceMappingURL=adoption.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adoption.d.ts","sourceRoot":"","sources":["../../src/baselines/adoption.ts"],"names":[],"mappings":"AAgBA,OAAO,
|
|
1
|
+
{"version":3,"file":"adoption.d.ts","sourceRoot":"","sources":["../../src/baselines/adoption.ts"],"names":[],"mappings":"AAgBA,OAAO,EAIL,KAAK,cAAc,EACnB,KAAK,cAAc,EACpB,MAAM,wBAAwB,CAAC;AAEhC,2EAA2E;AAC3E,eAAO,MAAM,wBAAwB,kBAAkB,CAAC;AAExD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAkBtE;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAwB9E;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAmBnF;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,cAAc,EACvB,WAAW,EAAE,SAAS,MAAM,EAAE,GAC7B,cAAc,CA8BhB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B,GAAG,cAAc,CA4BjB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,SAAS,MAAM,EAAE,GAC9B,cAAc,CAmChB"}
|
|
@@ -10,11 +10,11 @@
|
|
|
10
10
|
* schema-violating record throws — the gate must never guess whether an
|
|
11
11
|
* unreadable adoption record does or does not sanction the baseline.
|
|
12
12
|
*/
|
|
13
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
13
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs';
|
|
14
14
|
import { dirname } from 'node:path';
|
|
15
15
|
import { compareStrings } from '../graph/util.js';
|
|
16
16
|
import { GateforgeBaselineError } from './index.js';
|
|
17
|
-
import { AdoptionRecordSchema, ClassificationBlockedIdsSchema, } from '../schemas/adoption.js';
|
|
17
|
+
import { AdoptionFamilySchema, AdoptionRecordSchema, ClassificationBlockedIdsSchema, } from '../schemas/adoption.js';
|
|
18
18
|
/** The adoption record's fixed file name, beside the baseline document. */
|
|
19
19
|
export const ADOPTION_RECORD_FILENAME = 'adoption.json';
|
|
20
20
|
/**
|
|
@@ -55,19 +55,43 @@ export function loadAdoptionRecord(path) {
|
|
|
55
55
|
* needed. Serialized sorted 2-space JSON with a trailing newline
|
|
56
56
|
* (reviewable in diffs, like the baseline document).
|
|
57
57
|
*
|
|
58
|
+
* The receipt is the ONE sanction record a repository cannot regenerate,
|
|
59
|
+
* so the write is validated BEFORE any filesystem mutation and then
|
|
60
|
+
* ATOMIC: the serialized bytes go to a same-directory temporary file and
|
|
61
|
+
* `rename` over the destination. A crash or a failed write can never
|
|
62
|
+
* leave the receipt truncated or half-written — the previous receipt
|
|
63
|
+
* stays intact and in force, and the temporary file is removed on any
|
|
64
|
+
* failure (cleanup errors never mask the write error).
|
|
65
|
+
*
|
|
58
66
|
* Args:
|
|
59
67
|
* path: destination file path.
|
|
60
|
-
* record: the
|
|
68
|
+
* record: the adoption record to persist.
|
|
61
69
|
*
|
|
62
70
|
* Throws:
|
|
63
|
-
* GateforgeBaselineError: when the
|
|
71
|
+
* GateforgeBaselineError: when the record fails validation or the file
|
|
72
|
+
* cannot be written (the previous receipt, if any, is untouched).
|
|
64
73
|
*/
|
|
65
74
|
export function writeAdoptionRecord(path, record) {
|
|
75
|
+
let serialized;
|
|
76
|
+
try {
|
|
77
|
+
serialized = `${JSON.stringify(AdoptionRecordSchema.parse(record), null, 2)}\n`;
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
throw new GateforgeBaselineError(`adoption record '${path}' failed validation before write: ${error instanceof Error ? error.message : String(error)}`);
|
|
81
|
+
}
|
|
82
|
+
const temporary = `${path}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`;
|
|
66
83
|
try {
|
|
67
84
|
mkdirSync(dirname(path), { recursive: true });
|
|
68
|
-
writeFileSync(
|
|
85
|
+
writeFileSync(temporary, serialized, 'utf8');
|
|
86
|
+
renameSync(temporary, path);
|
|
69
87
|
}
|
|
70
88
|
catch (error) {
|
|
89
|
+
try {
|
|
90
|
+
rmSync(temporary, { force: true });
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
// A failed cleanup must never mask the write failure itself.
|
|
94
|
+
}
|
|
71
95
|
throw new GateforgeBaselineError(`adoption record '${path}' could not be written: ${error instanceof Error ? error.message : String(error)}`);
|
|
72
96
|
}
|
|
73
97
|
}
|
|
@@ -160,4 +184,119 @@ export function shrinkClassificationBlocked(current, resourceIds) {
|
|
|
160
184
|
: { ...current, classificationBlocked: [] };
|
|
161
185
|
return AdoptionRecordSchema.parse(next);
|
|
162
186
|
}
|
|
187
|
+
/**
|
|
188
|
+
* Builds one family's permanent marker (0.13): the named, dated,
|
|
189
|
+
* commit-referenced slice a post-adoption migration records in the
|
|
190
|
+
* EXISTING receipt. `fingerprintsById` must already contain EVERY
|
|
191
|
+
* initial family obligation id — proven obligations included — keyed by
|
|
192
|
+
* obligation id with its pin-#2 fingerprint; `forgiven` names the
|
|
193
|
+
* sanctioned subset (only what was missing/unproven). Input order is
|
|
194
|
+
* irrelevant: the marker is normalized to sorted keys and a sorted,
|
|
195
|
+
* duplicate-free `forgiven` list, so the receipt bytes are deterministic
|
|
196
|
+
* (and with them the trusted-policy digest that binds the marker).
|
|
197
|
+
*
|
|
198
|
+
* Args:
|
|
199
|
+
* input.adoptedAt: the family adoption instant (run's injected clock).
|
|
200
|
+
* input.gitSha: HEAD sha of the adopting commit, or null outside git.
|
|
201
|
+
* input.fingerprintsById: every initial family obligation id → fingerprint.
|
|
202
|
+
* input.forgiven: the sanctioned (missing/unproven) subset to forgive.
|
|
203
|
+
*
|
|
204
|
+
* Returns:
|
|
205
|
+
* AdoptionFamily: the validated marker for the receipt's `families` map.
|
|
206
|
+
*
|
|
207
|
+
* Throws:
|
|
208
|
+
* GateforgeBaselineError: when a forgiven fingerprint is not one of the
|
|
209
|
+
* recorded ones, a fingerprint is malformed, or an id is empty (fail
|
|
210
|
+
* closed — a marker that forgives beyond its own record is never built).
|
|
211
|
+
*/
|
|
212
|
+
export function adoptFamily(input) {
|
|
213
|
+
const seen = {};
|
|
214
|
+
const unique = [];
|
|
215
|
+
for (const fingerprint of input.forgiven) {
|
|
216
|
+
if (fingerprint in seen)
|
|
217
|
+
continue;
|
|
218
|
+
seen[fingerprint] = true;
|
|
219
|
+
unique.push(fingerprint);
|
|
220
|
+
}
|
|
221
|
+
unique.sort(compareStrings);
|
|
222
|
+
const recorded = {};
|
|
223
|
+
for (const id of Object.keys(input.fingerprintsById).sort(compareStrings)) {
|
|
224
|
+
recorded[id] = input.fingerprintsById[id];
|
|
225
|
+
}
|
|
226
|
+
const candidate = {
|
|
227
|
+
schemaVersion: 1,
|
|
228
|
+
adoptedAt: input.adoptedAt,
|
|
229
|
+
gitSha: input.gitSha,
|
|
230
|
+
fingerprintsById: recorded,
|
|
231
|
+
forgiven: unique,
|
|
232
|
+
};
|
|
233
|
+
const result = AdoptionFamilySchema.safeParse(candidate);
|
|
234
|
+
if (!result.success) {
|
|
235
|
+
const issues = result.error.issues
|
|
236
|
+
.map((issue) => `${issue.path.join('.') || '<family>'}: ${issue.message}`)
|
|
237
|
+
.join('; ');
|
|
238
|
+
throw new GateforgeBaselineError(`adoption family marker failed validation: ${issues}`);
|
|
239
|
+
}
|
|
240
|
+
return result.data;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* A family's ONLY mutation after adoption (the shrink path, mirroring
|
|
244
|
+
* `updateBaseline`'s GF-07/08 semantics and the classification set's):
|
|
245
|
+
* replaces the named family's `forgiven` list with the given
|
|
246
|
+
* fingerprints, which must be a STRICT SUBSET of the current ones —
|
|
247
|
+
* every fingerprint kept must exist today AND at least one must be
|
|
248
|
+
* removed. The marker itself is retained untouched (adoptedAt, gitSha,
|
|
249
|
+
* every recorded fingerprint), so a repeat migration can never re-arm
|
|
250
|
+
* and a resolved debt can never re-enter: the sanctioned set can only
|
|
251
|
+
* shrink.
|
|
252
|
+
*
|
|
253
|
+
* Args:
|
|
254
|
+
* current: the adopted record on disk.
|
|
255
|
+
* name: the family to shrink (only `pages` exists today).
|
|
256
|
+
* fingerprints: the fingerprints to KEEP (duplicates are an error, as
|
|
257
|
+
* in `updateBaseline`; an empty list keeps none).
|
|
258
|
+
*
|
|
259
|
+
* Returns:
|
|
260
|
+
* AdoptionRecord: the next record — identical to `current` except for
|
|
261
|
+
* the named family's shrunk `forgiven` list.
|
|
262
|
+
*
|
|
263
|
+
* Throws:
|
|
264
|
+
* GateforgeBaselineError: when the record carries no such family
|
|
265
|
+
* marker, on duplicate input, on schema-invalid fingerprints, or on a
|
|
266
|
+
* non-strict-subset update (naming the unknown or added fingerprints).
|
|
267
|
+
*/
|
|
268
|
+
export function shrinkFamilyForgiven(current, name, fingerprints) {
|
|
269
|
+
const family = current.families?.[name];
|
|
270
|
+
if (family === undefined) {
|
|
271
|
+
throw new GateforgeBaselineError(`family shrink rejected: the adoption record carries no '${name}' family marker ` +
|
|
272
|
+
'(the family is adopted exactly once, by `gateforge adopt --family <name> --confirm`) — ' +
|
|
273
|
+
'there is nothing to shrink');
|
|
274
|
+
}
|
|
275
|
+
const seen = {};
|
|
276
|
+
const unique = [];
|
|
277
|
+
for (const fingerprint of fingerprints) {
|
|
278
|
+
if (fingerprint in seen)
|
|
279
|
+
continue;
|
|
280
|
+
seen[fingerprint] = true;
|
|
281
|
+
unique.push(fingerprint);
|
|
282
|
+
}
|
|
283
|
+
if (unique.length !== fingerprints.length) {
|
|
284
|
+
throw new GateforgeBaselineError(`family '${name}' shrink input contains duplicate fingerprints`);
|
|
285
|
+
}
|
|
286
|
+
const known = {};
|
|
287
|
+
for (const fingerprint of family.forgiven)
|
|
288
|
+
known[fingerprint] = true;
|
|
289
|
+
const unknown = unique.filter((fingerprint) => !(fingerprint in known));
|
|
290
|
+
if (unique.length >= family.forgiven.length || unknown.length > 0) {
|
|
291
|
+
throw new GateforgeBaselineError(`family '${name}' shrink rejected: not a strict subset of the forgiven set ` +
|
|
292
|
+
'(the family set is shrink-only) — unknown or added fingerprint(s): ' +
|
|
293
|
+
`${(unknown.length > 0 ? unknown : unique).join(', ') || '<none>'}`);
|
|
294
|
+
}
|
|
295
|
+
const families = {};
|
|
296
|
+
for (const key of Object.keys(current.families ?? {}).sort(compareStrings)) {
|
|
297
|
+
families[key] = key === name ? { ...family, forgiven: unique.sort(compareStrings) } : current.families[key];
|
|
298
|
+
}
|
|
299
|
+
const next = { ...current, families };
|
|
300
|
+
return AdoptionRecordSchema.parse(next);
|
|
301
|
+
}
|
|
163
302
|
//# sourceMappingURL=adoption.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adoption.js","sourceRoot":"","sources":["../../src/baselines/adoption.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"adoption.js","sourceRoot":"","sources":["../../src/baselines/adoption.ts"],"names":[],"mappings":"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"}
|
|
@@ -127,6 +127,7 @@ export declare const RULES: {
|
|
|
127
127
|
readonly exposurePositive: "EXPOSURE_POSITIVE_SIGNAL";
|
|
128
128
|
readonly exposureInternalCertificate: "EXPOSURE_INTERNAL_CERTIFICATE";
|
|
129
129
|
readonly exposureDefault: "EXPOSURE_DEFAULT_USER_FACING";
|
|
130
|
+
readonly exposurePageAudience: "EXPOSURE_PAGE_AUDIENCE";
|
|
130
131
|
readonly exposureOperationalProbe: "EXPOSURE_OPERATIONAL_PROBE";
|
|
131
132
|
readonly lifecyclePositive: "LIFECYCLE_POSITIVE_SIGNAL";
|
|
132
133
|
readonly lifecycleDeclaredSupported: "LIFECYCLE_DECLARED_SUPPORTED";
|
|
@@ -138,6 +139,8 @@ export declare const RULES: {
|
|
|
138
139
|
readonly deleteOwnerRule: "DELETE_SEMANTICS_OWNER_RULE";
|
|
139
140
|
readonly planeEvidence: "PLANE_DETECTOR_EVIDENCE";
|
|
140
141
|
readonly lifecycleEndpointHttp: "LIFECYCLE_ENDPOINT_HTTP";
|
|
142
|
+
readonly lifecyclePageObservation: "LIFECYCLE_PAGE_OBSERVATION";
|
|
143
|
+
readonly identityPageRoute: "IDENTITY_PAGE_ROUTE";
|
|
141
144
|
readonly identityEvidence: "IDENTITY_DETECTOR_EVIDENCE";
|
|
142
145
|
readonly adapterNameMatch: "ADAPTER_NAME_MATCH";
|
|
143
146
|
readonly orgInternalRule: "ORGANIZATION_INTERNAL_RULE";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../../src/classifier/classify.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAwB,KAAK,cAAc,EAAkB,MAAM,8BAA8B,CAAC;AAKzG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAY,KAAK,oBAAoB,EAAwB,MAAM,qCAAqC,CAAC;AAChH,OAAO,EAEL,KAAK,eAAe,EAEpB,KAAK,2BAA2B,EAEjC,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../../src/classifier/classify.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,11 +23,13 @@ import { signalId } from '../schemas/classification-signal.js';
|
|
|
23
23
|
import { BLOCK_DIMENSIONS, } from './schema.js';
|
|
24
24
|
import { globMatch } from './glob.js';
|
|
25
25
|
import { HTTP_ENDPOINT_RESOURCE_KIND } from '../graph/schema.js';
|
|
26
|
+
const UI_PAGE_RESOURCE_KIND = 'ui.page';
|
|
26
27
|
/** Stable rule ids rendered in decision traces (ADR 0003 D2). */
|
|
27
28
|
export const RULES = {
|
|
28
29
|
exposurePositive: 'EXPOSURE_POSITIVE_SIGNAL',
|
|
29
30
|
exposureInternalCertificate: 'EXPOSURE_INTERNAL_CERTIFICATE',
|
|
30
31
|
exposureDefault: 'EXPOSURE_DEFAULT_USER_FACING',
|
|
32
|
+
exposurePageAudience: 'EXPOSURE_PAGE_AUDIENCE',
|
|
31
33
|
exposureOperationalProbe: 'EXPOSURE_OPERATIONAL_PROBE',
|
|
32
34
|
lifecyclePositive: 'LIFECYCLE_POSITIVE_SIGNAL',
|
|
33
35
|
lifecycleDeclaredSupported: 'LIFECYCLE_DECLARED_SUPPORTED',
|
|
@@ -39,6 +41,8 @@ export const RULES = {
|
|
|
39
41
|
deleteOwnerRule: 'DELETE_SEMANTICS_OWNER_RULE',
|
|
40
42
|
planeEvidence: 'PLANE_DETECTOR_EVIDENCE',
|
|
41
43
|
lifecycleEndpointHttp: 'LIFECYCLE_ENDPOINT_HTTP',
|
|
44
|
+
lifecyclePageObservation: 'LIFECYCLE_PAGE_OBSERVATION',
|
|
45
|
+
identityPageRoute: 'IDENTITY_PAGE_ROUTE',
|
|
42
46
|
identityEvidence: 'IDENTITY_DETECTOR_EVIDENCE',
|
|
43
47
|
adapterNameMatch: 'ADAPTER_NAME_MATCH',
|
|
44
48
|
orgInternalRule: 'ORGANIZATION_INTERNAL_RULE',
|
|
@@ -816,6 +820,12 @@ function classifyOne(resource, pool, ctx) {
|
|
|
816
820
|
// -- Plane ----------------------------------------------------------------
|
|
817
821
|
const planeCandidates = new Set();
|
|
818
822
|
const attributePlane = resource.attributes['plane'];
|
|
823
|
+
if (resource.kind === UI_PAGE_RESOURCE_KIND &&
|
|
824
|
+
(typeof resource.attributes['audience'] !== 'string' ||
|
|
825
|
+
resource.attributes['audience'] === '' ||
|
|
826
|
+
resource.attributes['audience'] === 'unknown')) {
|
|
827
|
+
return blocked(resource, [planeUnresolvedBlock(resource, 'page audience is unresolved by pages.audiences')]);
|
|
828
|
+
}
|
|
819
829
|
if (attributePlane === 'tenant' || attributePlane === 'master' || attributePlane === 'global') {
|
|
820
830
|
planeCandidates.add(attributePlane);
|
|
821
831
|
}
|
|
@@ -869,7 +879,11 @@ function classifyOne(resource, pool, ctx) {
|
|
|
869
879
|
identityKeys.add(joinKeys(signal.assertion));
|
|
870
880
|
}
|
|
871
881
|
let primaryKey;
|
|
872
|
-
if (
|
|
882
|
+
if (resource.kind === UI_PAGE_RESOURCE_KIND) {
|
|
883
|
+
primaryKey = ['path'];
|
|
884
|
+
rules.push(RULES.identityPageRoute);
|
|
885
|
+
}
|
|
886
|
+
else if (identityKeys.size === 1) {
|
|
873
887
|
const only = [...identityKeys][0];
|
|
874
888
|
primaryKey = splitKeys(only);
|
|
875
889
|
rules.push(RULES.identityEvidence);
|
|
@@ -910,7 +924,11 @@ function classifyOne(resource, pool, ctx) {
|
|
|
910
924
|
(rule.match.resourceKind === undefined || rule.match.resourceKind === resource.kind));
|
|
911
925
|
const hasInternalIntent = internalDeclarations.length > 0 || matchedInternalRules.length > 0;
|
|
912
926
|
let exposure;
|
|
913
|
-
if (
|
|
927
|
+
if (resource.kind === UI_PAGE_RESOURCE_KIND) {
|
|
928
|
+
exposure = 'user-facing';
|
|
929
|
+
rules.push(RULES.exposurePageAudience);
|
|
930
|
+
}
|
|
931
|
+
else if (isOperationalEndpoint(resource)) {
|
|
914
932
|
// Operational probes (plan §6 "Health/operations") resolve through an
|
|
915
933
|
// engine-issued exposure lane, NOT the user-facing default and NOT an
|
|
916
934
|
// internality certificate: the class itself is positive compiler
|
|
@@ -1060,7 +1078,14 @@ function classifyOne(resource, pool, ctx) {
|
|
|
1060
1078
|
// contracts) have no honest meaning here and would only demand
|
|
1061
1079
|
// delete-semantics evidence no route can carry.
|
|
1062
1080
|
const lifecycle = { create: true, read: true, update: true, delete: true };
|
|
1063
|
-
if (resource.kind ===
|
|
1081
|
+
if (resource.kind === UI_PAGE_RESOURCE_KIND) {
|
|
1082
|
+
lifecycle.create = false;
|
|
1083
|
+
lifecycle.read = false;
|
|
1084
|
+
lifecycle.update = false;
|
|
1085
|
+
lifecycle.delete = false;
|
|
1086
|
+
rules.push(RULES.lifecyclePageObservation);
|
|
1087
|
+
}
|
|
1088
|
+
else if (resource.kind === HTTP_ENDPOINT_RESOURCE_KIND) {
|
|
1064
1089
|
// ADR 0004 D5/D8: HTTP endpoints carry no lifecycle lattice. Their
|
|
1065
1090
|
// route semantics live in the compiled capabilities attribute, and
|
|
1066
1091
|
// the policy engine never generates crud:*/persistence:* contracts
|
|
@@ -1286,20 +1311,12 @@ function classifyOne(resource, pool, ctx) {
|
|
|
1286
1311
|
}
|
|
1287
1312
|
}
|
|
1288
1313
|
// -- Adapter binding -------------------------------------------------------
|
|
1289
|
-
//
|
|
1290
|
-
//
|
|
1291
|
-
//
|
|
1292
|
-
//
|
|
1293
|
-
//
|
|
1294
|
-
|
|
1295
|
-
// for a route, so demanding one for every user-facing endpoint was a
|
|
1296
|
-
// category error that red the gate on evidence no route can carry.
|
|
1297
|
-
// Endpoints therefore classify user-facing WITHOUT an adapter (the
|
|
1298
|
-
// claims lane, recorded as `evidenceLane: 'claims'` so the schema and
|
|
1299
|
-
// every downstream consumer see WHY no adapter is present). The demand
|
|
1300
|
-
// is unchanged for business kinds: a user-facing table without a
|
|
1301
|
-
// reviewed adapter still blocks (ADAPTER_MISSING).
|
|
1302
|
-
const businessResource = resource.kind !== HTTP_ENDPOINT_RESOURCE_KIND;
|
|
1314
|
+
// Reviewed EntityAdapters are required only for persisted business
|
|
1315
|
+
// resources. HTTP endpoints use the claims/witness-proxy lane; ui.page
|
|
1316
|
+
// resources are witness-observed routes with no persistence state.
|
|
1317
|
+
// Neither route kind has an honest EntityAdapter contract, while the
|
|
1318
|
+
// adapter demand remains unchanged for business kinds.
|
|
1319
|
+
const businessResource = resource.kind !== HTTP_ENDPOINT_RESOURCE_KIND && resource.kind !== UI_PAGE_RESOURCE_KIND;
|
|
1303
1320
|
let evidenceAdapter;
|
|
1304
1321
|
if (exposure === 'user-facing' && businessResource) {
|
|
1305
1322
|
const bound = bindAdapter(ctx.adapters, resource, signals);
|
|
@@ -1325,7 +1342,11 @@ function classifyOne(resource, pool, ctx) {
|
|
|
1325
1342
|
plane,
|
|
1326
1343
|
lifecycle,
|
|
1327
1344
|
primaryKey,
|
|
1328
|
-
...(exposure === 'user-facing' &&
|
|
1345
|
+
...(exposure === 'user-facing' && resource.kind === UI_PAGE_RESOURCE_KIND
|
|
1346
|
+
? { evidenceLane: 'page-observation' }
|
|
1347
|
+
: exposure === 'user-facing' && !businessResource
|
|
1348
|
+
? { evidenceLane: 'claims' }
|
|
1349
|
+
: {}),
|
|
1329
1350
|
...(evidenceAdapter !== undefined ? { evidenceAdapter } : {}),
|
|
1330
1351
|
};
|
|
1331
1352
|
const signalIds = [...new Set(contributing.map((s) => signalId(s)))].sort(compareStrings);
|