@plasius/schema 1.3.0 → 1.3.1

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.
Files changed (36) hide show
  1. package/README.md +188 -1
  2. package/THIRD_PARTY_NOTICES.md +75 -0
  3. package/dist/chunk-6FE4FLKF.js +254 -0
  4. package/dist/chunk-6FE4FLKF.js.map +1 -0
  5. package/dist/chunk-AG2NAPDC.js +117 -0
  6. package/dist/chunk-AG2NAPDC.js.map +1 -0
  7. package/dist/chunk-UQHPDQZX.js +2606 -0
  8. package/dist/chunk-UQHPDQZX.js.map +1 -0
  9. package/dist/feedback-diagnostics-BaniQAFS.d.cts +353 -0
  10. package/dist/feedback-diagnostics-CnsI0B9-.d.ts +353 -0
  11. package/dist/feedback-diagnostics-vocabulary.cjs +156 -0
  12. package/dist/feedback-diagnostics-vocabulary.cjs.map +1 -0
  13. package/dist/feedback-diagnostics-vocabulary.d.cts +70 -0
  14. package/dist/feedback-diagnostics-vocabulary.d.ts +70 -0
  15. package/dist/feedback-diagnostics-vocabulary.js +33 -0
  16. package/dist/feedback-diagnostics-vocabulary.js.map +1 -0
  17. package/dist/feedback-diagnostics.cjs +2696 -0
  18. package/dist/feedback-diagnostics.cjs.map +1 -0
  19. package/dist/feedback-diagnostics.d.cts +2 -0
  20. package/dist/feedback-diagnostics.d.ts +2 -0
  21. package/dist/feedback-diagnostics.js +39 -0
  22. package/dist/feedback-diagnostics.js.map +1 -0
  23. package/dist/feedback-unicode-profile.cjs +283 -0
  24. package/dist/feedback-unicode-profile.cjs.map +1 -0
  25. package/dist/feedback-unicode-profile.d.cts +28 -0
  26. package/dist/feedback-unicode-profile.d.ts +28 -0
  27. package/dist/feedback-unicode-profile.js +13 -0
  28. package/dist/feedback-unicode-profile.js.map +1 -0
  29. package/dist/index.cjs +2133 -14
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.d.cts +879 -286
  32. package/dist/index.d.ts +879 -286
  33. package/dist/index.js +1516 -2300
  34. package/dist/index.js.map +1 -1
  35. package/package.json +36 -12
  36. package/unicode/feedback-unicode-15.1.0-unassigned.json +13 -0
package/dist/index.cjs CHANGED
@@ -20,6 +20,58 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ FEEDBACK_ANALYSIS_MODEL_VERSIONS: () => FEEDBACK_ANALYSIS_MODEL_VERSIONS,
24
+ FEEDBACK_BACKEND_BUCKETS: () => FEEDBACK_BACKEND_BUCKETS,
25
+ FEEDBACK_BUG_COOLDOWN_SECONDS: () => FEEDBACK_BUG_COOLDOWN_SECONDS,
26
+ FEEDBACK_CONTRACT_VERSION: () => FEEDBACK_CONTRACT_VERSION,
27
+ FEEDBACK_FRAME_RATE_BUCKETS: () => FEEDBACK_FRAME_RATE_BUCKETS,
28
+ FEEDBACK_FRAME_TIME_BUCKETS: () => FEEDBACK_FRAME_TIME_BUCKETS,
29
+ FEEDBACK_GAME_COUNTER_CODES: () => FEEDBACK_GAME_COUNTER_CODES,
30
+ FEEDBACK_GAME_COUNTER_MAX_COUNT: () => FEEDBACK_GAME_COUNTER_MAX_COUNT,
31
+ FEEDBACK_GAME_COUNTER_MAX_ITEMS: () => FEEDBACK_GAME_COUNTER_MAX_ITEMS,
32
+ FEEDBACK_GAME_ERROR_CODES: () => FEEDBACK_GAME_ERROR_CODES,
33
+ FEEDBACK_GAME_FEATURE_IDS: () => FEEDBACK_GAME_FEATURE_IDS,
34
+ FEEDBACK_GAME_PROVENANCE_CONTRACTS: () => FEEDBACK_GAME_PROVENANCE_CONTRACTS,
35
+ FEEDBACK_GAME_PROVENANCE_CONTRACT_IDS: () => FEEDBACK_GAME_PROVENANCE_CONTRACT_IDS,
36
+ FEEDBACK_GAME_SURFACE_IDS: () => FEEDBACK_GAME_SURFACE_IDS,
37
+ FEEDBACK_INTENT_IDS: () => FEEDBACK_INTENT_IDS,
38
+ FEEDBACK_ISSUE_TYPES: () => FEEDBACK_ISSUE_TYPES,
39
+ FEEDBACK_PERSISTABLE_ISSUE_TYPES: () => FEEDBACK_PERSISTABLE_ISSUE_TYPES,
40
+ FEEDBACK_PRIVACY_POLICY_VERSIONS: () => FEEDBACK_PRIVACY_POLICY_VERSIONS,
41
+ FEEDBACK_RENDERER_BUCKETS: () => FEEDBACK_RENDERER_BUCKETS,
42
+ FEEDBACK_REVIEW_COOLDOWN_SECONDS: () => FEEDBACK_REVIEW_COOLDOWN_SECONDS,
43
+ FEEDBACK_SATISFACTION_LEVELS: () => FEEDBACK_SATISFACTION_LEVELS,
44
+ FEEDBACK_SENTIMENT_BUCKETS: () => FEEDBACK_SENTIMENT_BUCKETS,
45
+ FEEDBACK_SEVERITY_LEVELS: () => FEEDBACK_SEVERITY_LEVELS,
46
+ FEEDBACK_STRUCTURED_ONLY_REASON_CODES: () => FEEDBACK_STRUCTURED_ONLY_REASON_CODES,
47
+ FEEDBACK_SURFACE_DEFINITIONS: () => FEEDBACK_SURFACE_DEFINITIONS,
48
+ FEEDBACK_SURFACE_IDS: () => FEEDBACK_SURFACE_IDS,
49
+ FEEDBACK_THEME_IDS: () => FEEDBACK_THEME_IDS,
50
+ FEEDBACK_UNICODE_NORMALIZATION_PROFILE: () => FEEDBACK_UNICODE_NORMALIZATION_PROFILE,
51
+ FEEDBACK_VIEWPORT_BUCKETS: () => FEEDBACK_VIEWPORT_BUCKETS,
52
+ FeedbackAcceptanceReceiptSchema: () => FeedbackAcceptanceReceiptSchema,
53
+ FeedbackAnalysisReceiptSchema: () => FeedbackAnalysisReceiptSchema,
54
+ FeedbackBugPacketSchema: () => FeedbackBugPacketSchema,
55
+ FeedbackBugSubmissionRequestSchema: () => FeedbackBugSubmissionRequestSchema,
56
+ FeedbackContextSchema: () => FeedbackContextSchema,
57
+ FeedbackDailySatisfactionReportSchema: () => FeedbackDailySatisfactionReportSchema,
58
+ FeedbackDerivedAnalysisSchema: () => FeedbackDerivedAnalysisSchema,
59
+ FeedbackDraftPacketSchema: () => FeedbackDraftPacketSchema,
60
+ FeedbackDraftReceiptSchema: () => FeedbackDraftReceiptSchema,
61
+ FeedbackDraftUpsertRequestSchema: () => FeedbackDraftUpsertRequestSchema,
62
+ FeedbackEncryptedNarrativeEnvelopeSchema: () => FeedbackEncryptedNarrativeEnvelopeSchema,
63
+ FeedbackGameDiagnosticsSchema: () => FeedbackGameDiagnosticsSchema,
64
+ FeedbackGameReconstructionManifestSchema: () => FeedbackGameReconstructionManifestSchema,
65
+ FeedbackHourlyBugReportSchema: () => FeedbackHourlyBugReportSchema,
66
+ FeedbackMaterializationManifestSchema: () => FeedbackMaterializationManifestSchema,
67
+ FeedbackProcessorCheckpointSchema: () => FeedbackProcessorCheckpointSchema,
68
+ FeedbackPublicSummarySchema: () => FeedbackPublicSummarySchema,
69
+ FeedbackReviewPacketSchema: () => FeedbackReviewPacketSchema,
70
+ FeedbackReviewSubmissionRequestSchema: () => FeedbackReviewSubmissionRequestSchema,
71
+ FeedbackRichTextAstSchema: () => FeedbackRichTextAstSchema,
72
+ FeedbackStructuredOnlyAnalysisResultSchema: () => FeedbackStructuredOnlyAnalysisResultSchema,
73
+ FeedbackSurfaceCatalogSchema: () => FeedbackSurfaceCatalogSchema,
74
+ FeedbackTransientAnalysisRequestSchema: () => FeedbackTransientAnalysisRequestSchema,
23
75
  FieldBuilder: () => FieldBuilder,
24
76
  IsoLanguageCode: () => IsoLanguageCode,
25
77
  PLAYER_SYSTEM_ACHIEVEMENT_TIERS: () => PLAYER_SYSTEM_ACHIEVEMENT_TIERS,
@@ -28,6 +80,8 @@ __export(index_exports, {
28
80
  PlayerSystemCuratedSnapshotSchema: () => PlayerSystemCuratedSnapshotSchema,
29
81
  PlayerSystemNormalizedEventBatchSchema: () => PlayerSystemNormalizedEventBatchSchema,
30
82
  PlayerSystemObservedEventBatchSchema: () => PlayerSystemObservedEventBatchSchema,
83
+ SCHEMA_IDENTITY_POLICIES: () => SCHEMA_IDENTITY_POLICIES,
84
+ SCHEMA_UNKNOWN_FIELDS_POLICIES: () => SCHEMA_UNKNOWN_FIELDS_POLICIES,
31
85
  createComponentSchema: () => createComponentSchema,
32
86
  createSchema: () => createSchema,
33
87
  field: () => field,
@@ -50,7 +104,10 @@ __export(index_exports, {
50
104
  validateCountryCode: () => validateCountryCode,
51
105
  validateCurrencyCode: () => validateCurrencyCode,
52
106
  validateDateTimeISO: () => validateDateTimeISO,
107
+ validateDisplayName: () => validateDisplayName,
53
108
  validateEmail: () => validateEmail,
109
+ validateFeedbackGameDiagnostics: () => validateFeedbackGameDiagnostics,
110
+ validateFeedbackTransientAnalysisRequest: () => validateFeedbackTransientAnalysisRequest,
54
111
  validateLanguage: () => validateLanguage,
55
112
  validateName: () => validateName,
56
113
  validatePercentage: () => validatePercentage,
@@ -818,7 +875,7 @@ function validateRichText(value) {
818
875
  }
819
876
 
820
877
  // src/validation/name.OWASP.ts
821
- function validateName(value) {
878
+ function validateNameLike(value, pattern) {
822
879
  if (typeof value !== "string") return false;
823
880
  const trimmed = value.trim();
824
881
  if (trimmed.length === 0) return false;
@@ -827,10 +884,15 @@ function validateName(value) {
827
884
  const cp = ch.codePointAt(0);
828
885
  if (cp >= 0 && cp <= 31 || cp === 127) return false;
829
886
  }
830
- const namePattern = /^[\p{L}\p{M}'\-. ]+$/u;
831
- if (!namePattern.test(trimmed)) return false;
887
+ if (!pattern.test(trimmed)) return false;
832
888
  return true;
833
889
  }
890
+ function validateName(value) {
891
+ return validateNameLike(value, /^[\p{L}\p{M}'\-. ]+$/u);
892
+ }
893
+ function validateDisplayName(value) {
894
+ return validateNameLike(value, /^[\p{L}\p{M}\p{Nd}'\-. ]+$/u);
895
+ }
834
896
 
835
897
  // src/validation/user.MS-GOOGLE-APPLE.ts
836
898
  function validateUserId(value) {
@@ -1222,6 +1284,16 @@ var field = {
1222
1284
  )
1223
1285
  };
1224
1286
 
1287
+ // src/types.ts
1288
+ var SCHEMA_UNKNOWN_FIELDS_POLICIES = Object.freeze([
1289
+ "strip",
1290
+ "reject"
1291
+ ]);
1292
+ var SCHEMA_IDENTITY_POLICIES = Object.freeze([
1293
+ "compatible",
1294
+ "exact"
1295
+ ]);
1296
+
1225
1297
  // src/pii.ts
1226
1298
  function enforcePIIField(parentKey, key, value, def, enforcement = "none", errors, logger) {
1227
1299
  const path = parentKey ? `${parentKey}.${key}` : key;
@@ -1256,6 +1328,9 @@ function prepareForStorage(shape, input, encryptFn, hashFn) {
1256
1328
  if (!isMissing) out[key] = null;
1257
1329
  return;
1258
1330
  }
1331
+ if (isMissing && def.isRequired === false) {
1332
+ return;
1333
+ }
1259
1334
  if (def.type === "object" && def._shape) {
1260
1335
  const obj = {};
1261
1336
  for (const [childKey, childDef] of Object.entries(def._shape)) {
@@ -1301,6 +1376,7 @@ function prepareForRead(shape, stored, decryptFn) {
1301
1376
  const readValue = (def, key, container, ctx = {}) => {
1302
1377
  if (!def) return container?.[key];
1303
1378
  const action = def._pii?.action;
1379
+ const hasValue = container !== void 0 && container !== null && Object.prototype.hasOwnProperty.call(container, key);
1304
1380
  if (action === "encrypt") {
1305
1381
  const enc = container?.[key + "Encrypted"] ?? container?.[`${ctx.parentKey ?? key}Encrypted`];
1306
1382
  return enc === void 0 ? void 0 : decryptFn(enc);
@@ -1311,11 +1387,17 @@ function prepareForRead(shape, stored, decryptFn) {
1311
1387
  }
1312
1388
  if (action === "clear")
1313
1389
  return container?.hasOwnProperty(key) ? null : void 0;
1390
+ if (!hasValue && def.isRequired === false) {
1391
+ return void 0;
1392
+ }
1314
1393
  if (def.type === "object" && def._shape) {
1315
1394
  const obj = {};
1316
1395
  const source = container && Object.prototype.hasOwnProperty.call(container, key) ? container[key] : container ?? {};
1317
1396
  for (const [childKey, childDef] of Object.entries(def._shape)) {
1318
- obj[childKey] = readValue(childDef, childKey, source);
1397
+ const child = readValue(childDef, childKey, source);
1398
+ if (child !== void 0) {
1399
+ obj[childKey] = child;
1400
+ }
1319
1401
  }
1320
1402
  return obj;
1321
1403
  }
@@ -1331,7 +1413,10 @@ function prepareForRead(shape, stored, decryptFn) {
1331
1413
  const refShape = def._shape;
1332
1414
  if (refShape) {
1333
1415
  for (const [childKey, childDef] of Object.entries(refShape)) {
1334
- ref[childKey] = readValue(childDef, childKey, ref);
1416
+ const child = readValue(childDef, childKey, ref);
1417
+ if (child !== void 0) {
1418
+ ref[childKey] = child;
1419
+ }
1335
1420
  }
1336
1421
  }
1337
1422
  return ref;
@@ -1340,13 +1425,19 @@ function prepareForRead(shape, stored, decryptFn) {
1340
1425
  };
1341
1426
  const result = {};
1342
1427
  for (const key in shape) {
1343
- result[key] = readValue(shape[key], key, stored);
1428
+ const value = readValue(shape[key], key, stored);
1429
+ if (value !== void 0) {
1430
+ result[key] = value;
1431
+ }
1344
1432
  }
1345
1433
  return result;
1346
1434
  }
1347
1435
  function sanitizeForLog(shape, data, pseudonymFn) {
1348
1436
  const visit = (def, value, ctx = {}) => {
1349
1437
  if (!def) return void 0;
1438
+ if ((value === void 0 || value === null) && def.isRequired === false) {
1439
+ return void 0;
1440
+ }
1350
1441
  const handling = def._pii?.logHandling;
1351
1442
  if (handling === "omit") return void 0;
1352
1443
  if (handling === "redact") return "[REDACTED]";
@@ -1391,18 +1482,37 @@ function sanitizeForLog(shape, data, pseudonymFn) {
1391
1482
  }
1392
1483
  function getPiiAudit(shape) {
1393
1484
  const piiFields = [];
1394
- for (const key in shape) {
1395
- const def = shape[key];
1396
- if (!def) continue;
1485
+ const visit = (def, path) => {
1486
+ if (!def) return;
1397
1487
  if (def._pii && def._pii.classification !== "none") {
1398
1488
  piiFields.push({
1399
- field: key,
1489
+ field: path,
1400
1490
  classification: def._pii.classification,
1401
1491
  action: def._pii.action,
1402
1492
  logHandling: def._pii.logHandling,
1403
1493
  purpose: def._pii.purpose
1404
1494
  });
1405
1495
  }
1496
+ if ((def.type === "object" || def.type === "ref") && def._shape) {
1497
+ for (const [childKey, childDef] of Object.entries(def._shape)) {
1498
+ visit(childDef, `${path}.${childKey}`);
1499
+ }
1500
+ }
1501
+ if (def.type === "array" && def.itemType) {
1502
+ const itemPath = `${path}[]`;
1503
+ if ((def.itemType.type === "object" || def.itemType.type === "ref") && def.itemType._shape) {
1504
+ for (const [childKey, childDef] of Object.entries(
1505
+ def.itemType._shape
1506
+ )) {
1507
+ visit(childDef, `${itemPath}.${childKey}`);
1508
+ }
1509
+ } else {
1510
+ visit(def.itemType, itemPath);
1511
+ }
1512
+ }
1513
+ };
1514
+ for (const key in shape) {
1515
+ visit(shape[key], key);
1406
1516
  }
1407
1517
  return piiFields;
1408
1518
  }
@@ -1635,9 +1745,7 @@ function validateEnum(parentKey, value, enumValues) {
1635
1745
  if (Array.isArray(value)) {
1636
1746
  const invalid = value.filter((v) => !values.includes(v));
1637
1747
  if (invalid.length > 0) {
1638
- return `Field ${parentKey} contains invalid enum values: ${invalid.join(
1639
- ", "
1640
- )}`;
1748
+ return `Field ${parentKey} must contain only: ${values.join(", ")}`;
1641
1749
  }
1642
1750
  } else {
1643
1751
  if (!values.includes(value)) {
@@ -1671,6 +1779,126 @@ function getValidator(def) {
1671
1779
  function getShape(def) {
1672
1780
  return def?._shape ?? def?.shape ?? void 0;
1673
1781
  }
1782
+ var MAX_STRICT_VALIDATION_NODES = 1e4;
1783
+ var MAX_STRICT_VALIDATION_DEPTH = 256;
1784
+ var MAX_STRICT_VALIDATION_OBJECTS = MAX_STRICT_VALIDATION_NODES;
1785
+ function strictInputIsWithinComplexityLimit(input) {
1786
+ const pending = [
1787
+ { value: input, depth: 0 }
1788
+ ];
1789
+ const seen = /* @__PURE__ */ new WeakSet();
1790
+ let visitedNodes = 0;
1791
+ try {
1792
+ while (pending.length > 0) {
1793
+ const current = pending.pop();
1794
+ if (!current) {
1795
+ continue;
1796
+ }
1797
+ visitedNodes += 1;
1798
+ if (visitedNodes > MAX_STRICT_VALIDATION_NODES || current.depth > MAX_STRICT_VALIDATION_DEPTH) {
1799
+ return false;
1800
+ }
1801
+ if (typeof current.value !== "object" || current.value === null) {
1802
+ continue;
1803
+ }
1804
+ if (seen.has(current.value)) {
1805
+ return false;
1806
+ }
1807
+ seen.add(current.value);
1808
+ const keys = Object.keys(current.value);
1809
+ if (visitedNodes + pending.length + keys.length > MAX_STRICT_VALIDATION_NODES) {
1810
+ return false;
1811
+ }
1812
+ const record = current.value;
1813
+ for (const key of keys) {
1814
+ pending.push({
1815
+ value: record[key],
1816
+ depth: current.depth + 1
1817
+ });
1818
+ }
1819
+ }
1820
+ } catch {
1821
+ return false;
1822
+ }
1823
+ return true;
1824
+ }
1825
+ function strictReferenceShape(def) {
1826
+ return {
1827
+ type: { type: "string" },
1828
+ id: { type: "string" },
1829
+ ...getShape(def) ?? {}
1830
+ };
1831
+ }
1832
+ function unknownFieldLocations(value, shape, location = "root", state = {
1833
+ remainingObjects: MAX_STRICT_VALIDATION_OBJECTS,
1834
+ limitExceeded: false
1835
+ }) {
1836
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
1837
+ return [];
1838
+ }
1839
+ if (state.remainingObjects <= 0) {
1840
+ state.limitExceeded = true;
1841
+ return [];
1842
+ }
1843
+ state.remainingObjects -= 1;
1844
+ const record = value;
1845
+ const knownKeys = new Set(Object.keys(shape));
1846
+ const locations = /* @__PURE__ */ new Set();
1847
+ if (Object.keys(record).some((key) => !knownKeys.has(key))) {
1848
+ locations.add(location);
1849
+ }
1850
+ for (const [key, def] of Object.entries(shape)) {
1851
+ const child = record[key];
1852
+ if (child === void 0 || child === null) {
1853
+ continue;
1854
+ }
1855
+ const childLocation = location === "root" ? key : `${location}.${key}`;
1856
+ const childShape = getShape(def);
1857
+ if (def?.type === "object" && childShape) {
1858
+ for (const nestedLocation of unknownFieldLocations(
1859
+ child,
1860
+ childShape,
1861
+ childLocation,
1862
+ state
1863
+ )) {
1864
+ locations.add(nestedLocation);
1865
+ }
1866
+ continue;
1867
+ }
1868
+ const itemType = def?.itemType;
1869
+ if (def?.type === "array" && (itemType?.type === "object" || itemType?.type === "ref") && Array.isArray(child)) {
1870
+ const itemShape = itemType.type === "ref" ? strictReferenceShape(itemType) : getShape(itemType);
1871
+ if (!itemShape) {
1872
+ continue;
1873
+ }
1874
+ for (const [index, item] of child.entries()) {
1875
+ if (state.limitExceeded) {
1876
+ break;
1877
+ }
1878
+ for (const nestedLocation of unknownFieldLocations(
1879
+ item,
1880
+ itemShape,
1881
+ `${childLocation}[${index}]`,
1882
+ state
1883
+ )) {
1884
+ locations.add(nestedLocation);
1885
+ }
1886
+ }
1887
+ continue;
1888
+ }
1889
+ if (def?.type === "ref") {
1890
+ for (const nestedLocation of unknownFieldLocations(
1891
+ child,
1892
+ strictReferenceShape(def),
1893
+ childLocation,
1894
+ state
1895
+ )) {
1896
+ locations.add(nestedLocation);
1897
+ }
1898
+ }
1899
+ }
1900
+ return [...locations];
1901
+ }
1674
1902
  function normalizeValidationIssue(path, issue, defaultCode) {
1675
1903
  if (typeof issue === "string") {
1676
1904
  return {
@@ -2131,6 +2359,8 @@ function createSchema(_shape, entityType, options = {
2131
2359
  table: "",
2132
2360
  schemaValidator: () => true,
2133
2361
  piiEnforcement: "none",
2362
+ unknownFields: SCHEMA_UNKNOWN_FIELDS_POLICIES[0],
2363
+ identity: SCHEMA_IDENTITY_POLICIES[0],
2134
2364
  schemaUpgrade: void 0
2135
2365
  }) {
2136
2366
  const systemFields = {
@@ -2157,6 +2387,57 @@ function createSchema(_shape, entityType, options = {
2157
2387
  if (typeof input !== "object" || input === null) {
2158
2388
  return { valid: false, errors: ["Input must be an object"] };
2159
2389
  }
2390
+ if (options.unknownFields === "reject") {
2391
+ if (!strictInputIsWithinComplexityLimit(input)) {
2392
+ return {
2393
+ valid: false,
2394
+ errors: ["Strict validation complexity limit exceeded."],
2395
+ issues: [
2396
+ {
2397
+ path: "root",
2398
+ code: "validation_complexity_limit",
2399
+ message: "Strict validation complexity limit exceeded."
2400
+ }
2401
+ ]
2402
+ };
2403
+ }
2404
+ const scanState = {
2405
+ remainingObjects: MAX_STRICT_VALIDATION_OBJECTS,
2406
+ limitExceeded: false
2407
+ };
2408
+ const locations = unknownFieldLocations(
2409
+ input,
2410
+ schema._shape,
2411
+ "root",
2412
+ scanState
2413
+ );
2414
+ if (scanState.limitExceeded) {
2415
+ return {
2416
+ valid: false,
2417
+ errors: ["Strict validation complexity limit exceeded."],
2418
+ issues: [
2419
+ {
2420
+ path: "root",
2421
+ code: "validation_complexity_limit",
2422
+ message: "Strict validation complexity limit exceeded."
2423
+ }
2424
+ ]
2425
+ };
2426
+ }
2427
+ if (locations.length > 0) {
2428
+ return {
2429
+ valid: false,
2430
+ errors: locations.map(
2431
+ (location) => `Unknown fields are not allowed at ${location}.`
2432
+ ),
2433
+ issues: locations.map((location) => ({
2434
+ path: location,
2435
+ code: "unknown_fields",
2436
+ message: `Unknown fields are not allowed at ${location}.`
2437
+ }))
2438
+ };
2439
+ }
2440
+ }
2160
2441
  const working = typeof input === "object" && input !== null ? deepClone(input) : { ...input };
2161
2442
  if (working.type == null) working.type = entityType;
2162
2443
  if (working.version == null) working.version = version;
@@ -2179,6 +2460,19 @@ function createSchema(_shape, entityType, options = {
2179
2460
  working.type = entityType;
2180
2461
  working.version = toVersion;
2181
2462
  }
2463
+ if (options.identity === "exact" && (working.type !== entityType || working.version !== version)) {
2464
+ return {
2465
+ valid: false,
2466
+ errors: ["Schema type or version does not match the contract."],
2467
+ issues: [
2468
+ {
2469
+ path: "root",
2470
+ code: "schema_identity_mismatch",
2471
+ message: "Schema type or version does not match the contract."
2472
+ }
2473
+ ]
2474
+ };
2475
+ }
2182
2476
  for (const key in schema._shape) {
2183
2477
  const def = schema._shape[key];
2184
2478
  let value = working[key];
@@ -2261,7 +2555,11 @@ function createSchema(_shape, entityType, options = {
2261
2555
  }
2262
2556
  if (errors.length === 0 && options.schemaValidator) {
2263
2557
  const castValue = result;
2264
- if (!options.schemaValidator(castValue)) {
2558
+ const source = input;
2559
+ const validationContext = Object.freeze({
2560
+ wasProvided: (fieldName) => Object.prototype.hasOwnProperty.call(source, fieldName)
2561
+ });
2562
+ if (!options.schemaValidator(castValue, validationContext)) {
2265
2563
  errors.push("Schema-level validation failed.");
2266
2564
  }
2267
2565
  }
@@ -2678,8 +2976,1824 @@ var PlayerSystemCuratedSnapshotSchema = createSchema(
2678
2976
  piiEnforcement: "strict"
2679
2977
  }
2680
2978
  );
2979
+
2980
+ // src/feedback-contract-version.ts
2981
+ var FEEDBACK_CONTRACT_VERSION = "1.0.0";
2982
+
2983
+ // src/feedback-diagnostics-vocabulary.ts
2984
+ var FEEDBACK_RENDERER_BUCKETS = [
2985
+ "webgl2",
2986
+ "webgpu",
2987
+ "canvas2d",
2988
+ "unknown"
2989
+ ];
2990
+ var FEEDBACK_BACKEND_BUCKETS = [
2991
+ "browser",
2992
+ "worker",
2993
+ "unknown"
2994
+ ];
2995
+ var FEEDBACK_GAME_SURFACE_IDS = [
2996
+ "site.generator",
2997
+ "site.gpu-demo"
2998
+ ];
2999
+ var FEEDBACK_GAME_PROVENANCE_CONTRACTS = [
3000
+ {
3001
+ surfaceId: "site.generator",
3002
+ contractId: "generator.renderer-diagnostics.v1"
3003
+ },
3004
+ {
3005
+ surfaceId: "site.gpu-demo",
3006
+ contractId: "gpu-demo.renderer-diagnostics.v1"
3007
+ }
3008
+ ];
3009
+ var FEEDBACK_GAME_PROVENANCE_CONTRACT_IDS = [
3010
+ "generator.renderer-diagnostics.v1",
3011
+ "gpu-demo.renderer-diagnostics.v1"
3012
+ ];
3013
+ var FEEDBACK_GAME_FEATURE_IDS = [
3014
+ "renderer.initialisation",
3015
+ "renderer.frame-loop",
3016
+ "renderer.asset-loading",
3017
+ "renderer.input",
3018
+ "renderer.scene-generation",
3019
+ "renderer.post-processing"
3020
+ ];
3021
+ var FEEDBACK_GAME_COUNTER_CODES = [
3022
+ "frame-drop",
3023
+ "device-loss",
3024
+ "asset-load-failure",
3025
+ "shader-failure",
3026
+ "fallback-activation"
3027
+ ];
3028
+ var FEEDBACK_GAME_COUNTER_MAX_ITEMS = 32;
3029
+ var FEEDBACK_GAME_COUNTER_MAX_COUNT = 1e4;
3030
+ var FEEDBACK_GAME_ERROR_CODES = [
3031
+ "renderer.initialisation-failed",
3032
+ "renderer.device-lost",
3033
+ "renderer.asset-load-failed",
3034
+ "renderer.frame-budget-exceeded",
3035
+ "renderer.shader-failed",
3036
+ "renderer.unknown"
3037
+ ];
3038
+ var FEEDBACK_VIEWPORT_BUCKETS = [
3039
+ "small-portrait",
3040
+ "small-landscape",
3041
+ "medium-portrait",
3042
+ "medium-landscape",
3043
+ "large-portrait",
3044
+ "large-landscape",
3045
+ "unknown"
3046
+ ];
3047
+ var FEEDBACK_FRAME_RATE_BUCKETS = [
3048
+ "under-15",
3049
+ "15-29",
3050
+ "30-59",
3051
+ "60-plus",
3052
+ "unknown"
3053
+ ];
3054
+ var FEEDBACK_FRAME_TIME_BUCKETS = [
3055
+ "under-17ms",
3056
+ "17-33ms",
3057
+ "34-66ms",
3058
+ "over-66ms",
3059
+ "unknown"
3060
+ ];
3061
+ for (const vocabulary of [
3062
+ FEEDBACK_RENDERER_BUCKETS,
3063
+ FEEDBACK_BACKEND_BUCKETS,
3064
+ FEEDBACK_GAME_SURFACE_IDS,
3065
+ FEEDBACK_GAME_PROVENANCE_CONTRACTS,
3066
+ FEEDBACK_GAME_PROVENANCE_CONTRACT_IDS,
3067
+ FEEDBACK_GAME_FEATURE_IDS,
3068
+ FEEDBACK_GAME_COUNTER_CODES,
3069
+ FEEDBACK_GAME_ERROR_CODES,
3070
+ FEEDBACK_VIEWPORT_BUCKETS,
3071
+ FEEDBACK_FRAME_RATE_BUCKETS,
3072
+ FEEDBACK_FRAME_TIME_BUCKETS
3073
+ ]) {
3074
+ Object.freeze(vocabulary);
3075
+ }
3076
+ for (const entry of FEEDBACK_GAME_PROVENANCE_CONTRACTS) {
3077
+ Object.freeze(entry);
3078
+ }
3079
+
3080
+ // src/feedback-diagnostics.contract.ts
3081
+ var positiveCountField = (maximum) => field.number().validator((value) => Number.isSafeInteger(value)).min(1).max(maximum);
3082
+ var nestedIdentityShape = () => ({
3083
+ type: field.string().enum(["feedback-game-diagnostics"]),
3084
+ version: field.string().enum([FEEDBACK_CONTRACT_VERSION])
3085
+ });
3086
+ var gameCounterShape = () => ({
3087
+ code: field.string().enum(FEEDBACK_GAME_COUNTER_CODES),
3088
+ count: positiveCountField(FEEDBACK_GAME_COUNTER_MAX_COUNT)
3089
+ });
3090
+ var feedbackGameDiagnosticsShape = (includeIdentity = false) => ({
3091
+ ...includeIdentity ? nestedIdentityShape() : {},
3092
+ surfaceId: field.string().enum(FEEDBACK_GAME_SURFACE_IDS),
3093
+ consentConfirmed: field.boolean(),
3094
+ provenanceContractId: field.string().enum(FEEDBACK_GAME_PROVENANCE_CONTRACT_IDS),
3095
+ renderer: field.string().enum(FEEDBACK_RENDERER_BUCKETS),
3096
+ backend: field.string().enum(FEEDBACK_BACKEND_BUCKETS),
3097
+ viewportBucket: field.string().enum(FEEDBACK_VIEWPORT_BUCKETS),
3098
+ frameRateBucket: field.string().enum(FEEDBACK_FRAME_RATE_BUCKETS),
3099
+ frameTimeBucket: field.string().enum(FEEDBACK_FRAME_TIME_BUCKETS),
3100
+ featureIds: field.array(field.string().enum(FEEDBACK_GAME_FEATURE_IDS)).max(FEEDBACK_GAME_FEATURE_IDS.length),
3101
+ counters: field.array(field.object(gameCounterShape())).max(FEEDBACK_GAME_COUNTER_MAX_ITEMS),
3102
+ errorCodes: field.array(field.string().enum(FEEDBACK_GAME_ERROR_CODES)).max(FEEDBACK_GAME_ERROR_CODES.length)
3103
+ });
3104
+ var isFeedbackGameDiagnosticsConsistent = (value) => {
3105
+ const featureIds = Array.isArray(value.featureIds) ? value.featureIds : [];
3106
+ const errorCodes = Array.isArray(value.errorCodes) ? value.errorCodes : [];
3107
+ const counters = Array.isArray(value.counters) ? value.counters : [];
3108
+ const provenance = FEEDBACK_GAME_PROVENANCE_CONTRACTS.find(
3109
+ ({ surfaceId }) => surfaceId === value.surfaceId
3110
+ );
3111
+ return value.consentConfirmed === true && provenance !== void 0 && provenance.contractId === value.provenanceContractId && new Set(featureIds).size === featureIds.length && new Set(errorCodes).size === errorCodes.length && new Set(
3112
+ counters.map(
3113
+ (counter) => typeof counter === "object" && counter !== null ? counter.code : void 0
3114
+ )
3115
+ ).size === counters.length;
3116
+ };
3117
+ var FeedbackGameDiagnosticsSchema = createSchema(
3118
+ feedbackGameDiagnosticsShape(),
3119
+ "feedback-game-diagnostics",
3120
+ {
3121
+ version: FEEDBACK_CONTRACT_VERSION,
3122
+ piiEnforcement: "strict",
3123
+ unknownFields: "reject",
3124
+ identity: "exact",
3125
+ schemaValidator: isFeedbackGameDiagnosticsConsistent
3126
+ }
3127
+ );
3128
+ var validateFeedbackGameDiagnostics = (input) => {
3129
+ const result = FeedbackGameDiagnosticsSchema.validate(input);
3130
+ if (!result.valid || result.value === void 0) {
3131
+ return {
3132
+ valid: false,
3133
+ errors: result.errors ?? ["Game diagnostics validation failed."],
3134
+ ...result.issues === void 0 ? {} : { issues: result.issues }
3135
+ };
3136
+ }
3137
+ return {
3138
+ valid: true,
3139
+ value: result.value
3140
+ };
3141
+ };
3142
+
3143
+ // unicode/feedback-unicode-15.1.0-unassigned.json
3144
+ var feedback_unicode_15_1_0_unassigned_default = {
3145
+ profileId: "unicode-15.1.0-nfkc-v1",
3146
+ unicodeVersion: "15.1.0",
3147
+ sourcePackage: "@unicode/unicode-15.1.0",
3148
+ sourcePackageVersion: "1.6.17",
3149
+ sourceProperty: "General_Category/Unassigned",
3150
+ rangeEncoding: "flat-half-open-delta-uleb128-base64url-v1",
3151
+ rangeCount: 707,
3152
+ endpointCount: 1414,
3153
+ codePointCount: 824718,
3154
+ endpointSha256: "591e457524d6b4b988aa7c7687e76c95a78370fea38bbd1b09085be7fd935ef3",
3155
+ payload: "-AYCBgQHAQEBFAGNAwEmAjICAwE3CBsEBguOAgE8AmUOOwIxAg8BHAIBAQsFHwECBuwBAQgCAgIWAQcBAQMEAgkCAgIECAEEAgEFAhkCAwEGBAICFgEHAQIBAgECAgEBBQQCAgMDAQcEAQEHEQoDAQkBAwEWAQcBAgEFAgoBAwEDAgEPBAIMBwcBAwEIAgICFgEHAQIBBQIJAgICAwcDBAIBBQISCgIBBgMDAQQDAgEBAQIDAgMDAwwEBQMDAQQCAQYBDhUFDQEDARcBEAIJAQMBBAcCAQMCAQIEAgoHFgEDARcBCgEFAgkBAwEEBwIGAgEEAgoBAwwNAQMBMwEDAQYEEAIaAQMBEgMYAQkBAQIHAwEEBgEBAQgGCgIDDDoEHSUCAQEBBQEYAQEBFwIFAQEBBwEKAgQgSAEkBCcBJAEPAQ0lxgEBAQUBAvkCAQQCBwEBAQQCKQEEAiEBBAIHAQEBBAIPATkBBAJDAiADGgZWAgYCnQUDWQcWCRgJFAwNAQMBAgxeAgoGCgYaBlkHKwVGCh8BDAQMBAEDKgIFCywEGgYLAz4CQQEdAgsGCgYOAh8xTQMvAXQIPAMPAzwHKwILCCsFlgQCBgImAgYCCAEBAQEBAQEfAjUBDwEOAgYBEwIDAQkBZQEMAhsBDQMhDyEPjAEElwUZCxWUDgIgAd0CBS0BAQUBAjgHAg4YCQcBBwEHAQcBBwEHAQcBBwF-IhoBWQzWARpQAVYCZwUrAV4BVAswAe3kAQM3CdwCFLgBCMsBBQIBAQEFGDsDCgY4CEYIDAZ0Cx4DTgELBCEBNwkOAgoCZxgcCgYCBgIGCQcBBwE8BH4CCgakVwwXBDEE7kQCaiYHDAUFGgEFAQEBAgECAX0QvQMCNgcBICoGMwETAQQEBQGHAQIBAb4BAwYCBgIGAgMDBwEHCgUCDAEaARMBAgEPAg4iewUDBC0DWAENAwEvLoIBHQMxDxwEJAkeBSsFHgElBA4qngECCgYkBCQEKAg0CwwBDwEHAQIBCwEPAQcBAkO3AgkWCggYBgEqAQlFBgIBASwBAgMBAhcBSAgJMBMBAgUhAxsFAUA4BBQCMgECBQgBAwEdAgMECgcJB0AgJwQMCTYDHQIbBRoHBAwHUEk3Mw0zBy4ICqYCHwEqAQMCAksrCCoWGiYcFBcJTgQkCUQKAQIZBwoGNQESCCcJYAEUCxIBLz4HAQEBBAEPAQsGOwUKBgQBCAICAhYBBwECAQUBCgICAgMCAQYBBQcCBwMFiwFcAQUeSAgKpgE2AiYiRQsKBg0TOgYKNhsCDwQXuQE8ZFMMCAIBAggBAgEeAQICDAkKRggCLgILG0gIUw1JBwr2AQkBLQEOCh0DIAIWAQ5JBwECASwDAQECAQkICgYGAQIBJQECAQYHCrYCGQcRASkDHFYBDzINmwdmbwEFC8QBzBRjDdYIqh_HBLlDuQQHHwEKBFEBCgYeAgYKRgoKAQcBFQUTsAVbZUsEOQcRQAULAg74LwjWCSoJ50UEAQcBAgGjAg8BHQMCAQ4ECIwDhBJrBQ0DCQcKAgjcJC4CFwl0PPYBCicCwgEVRnoUDBQMVwkZhwFVAUcBAgIBAgICBAEMAQEBBwFBAQQCCAEHARwBBAEFAQEDBwHUAgKkAgK-BQ8FAQ_QCB8GBtUBBwERAgcBAgEFBT4hAXAtAw4CCgQCwAIfEToFAdADKuYFBwEEAQIBDwHFAQIQKUwECgQCkQZETD3CAQQBGwECAQECAQEKAQQBAQEBBgEEAQEBAQEBAwECAQECAQEBAQEBAQEBAQIBAQIEAQcBBAEEAQEBCgERBQMBBQERNAKOAiwEZAwPAg8BDwElCq4BOB0NLAQJBwIOBpoB2AcEEQMNA3cEXwYMBAEPDAQ4CAoGKAgeAgJO1AIMDgINAwkHLgEHCA4ECQcJB5MBATclCoYI4M0CILogBt4BAoItDrE6D-4EohOeBOILyyYF4CDRuCsBHmCAAfABkPwD_v8DAv7_AwI"
3156
+ };
3157
+
3158
+ // src/feedback-unicode-profile.codec.ts
3159
+ var BASE64URL_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
3160
+ var BASE64URL_PATTERN = /^[A-Za-z0-9_-]+$/;
3161
+ var MAX_UNICODE_ENDPOINT = 1114112;
3162
+ var MAX_ENCODED_PAYLOAD_CHARACTERS = 8192;
3163
+ var MAX_ULEB128_BYTES = 5;
3164
+ var MAX_PROFILE_RANGE_COUNT = 707;
3165
+ var MAX_PROFILE_ENDPOINT_COUNT = MAX_PROFILE_RANGE_COUNT * 2;
3166
+ var MAX_PROFILE_CODE_POINT_COUNT = MAX_UNICODE_ENDPOINT;
3167
+ var ARTIFACT_KEYS = /* @__PURE__ */ new Set([
3168
+ "profileId",
3169
+ "unicodeVersion",
3170
+ "sourcePackage",
3171
+ "sourcePackageVersion",
3172
+ "sourceProperty",
3173
+ "rangeEncoding",
3174
+ "rangeCount",
3175
+ "endpointCount",
3176
+ "codePointCount",
3177
+ "endpointSha256",
3178
+ "payload"
3179
+ ]);
3180
+ function isRecord(value) {
3181
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3182
+ }
3183
+ function hasExpectedMetadata(artifact, expected) {
3184
+ return Object.keys(artifact).length === ARTIFACT_KEYS.size && Object.keys(artifact).every((key) => ARTIFACT_KEYS.has(key)) && artifact.profileId === expected.profileId && artifact.unicodeVersion === expected.unicodeVersion && artifact.sourcePackage === expected.sourcePackage && artifact.sourcePackageVersion === expected.sourcePackageVersion && artifact.sourceProperty === expected.sourceProperty && artifact.rangeEncoding === expected.rangeEncoding && artifact.rangeCount === expected.rangeCount && artifact.endpointCount === expected.endpointCount && artifact.codePointCount === expected.codePointCount && artifact.endpointSha256 === expected.endpointSha256;
3185
+ }
3186
+ function isBoundedPositiveInteger(value, maximum) {
3187
+ return typeof value === "number" && Number.isSafeInteger(value) && value > 0 && value <= maximum;
3188
+ }
3189
+ function hasBoundedCounts(artifact, expected) {
3190
+ return isBoundedPositiveInteger(
3191
+ artifact.rangeCount,
3192
+ MAX_PROFILE_RANGE_COUNT
3193
+ ) && isBoundedPositiveInteger(
3194
+ expected.rangeCount,
3195
+ MAX_PROFILE_RANGE_COUNT
3196
+ ) && isBoundedPositiveInteger(
3197
+ artifact.endpointCount,
3198
+ MAX_PROFILE_ENDPOINT_COUNT
3199
+ ) && isBoundedPositiveInteger(
3200
+ expected.endpointCount,
3201
+ MAX_PROFILE_ENDPOINT_COUNT
3202
+ ) && artifact.endpointCount === artifact.rangeCount * 2 && expected.endpointCount === expected.rangeCount * 2 && isBoundedPositiveInteger(
3203
+ artifact.codePointCount,
3204
+ MAX_PROFILE_CODE_POINT_COUNT
3205
+ ) && isBoundedPositiveInteger(
3206
+ expected.codePointCount,
3207
+ MAX_PROFILE_CODE_POINT_COUNT
3208
+ );
3209
+ }
3210
+ function decodeCanonicalBase64Url(value) {
3211
+ if (value.length === 0 || value.length > MAX_ENCODED_PAYLOAD_CHARACTERS || value.length % 4 === 1 || !BASE64URL_PATTERN.test(value)) {
3212
+ return void 0;
3213
+ }
3214
+ const finalSextet = BASE64URL_ALPHABET.indexOf(value.at(-1) ?? "");
3215
+ if (finalSextet < 0 || value.length % 4 === 2 && (finalSextet & 15) !== 0 || value.length % 4 === 3 && (finalSextet & 3) !== 0) {
3216
+ return void 0;
3217
+ }
3218
+ const expectedByteCount = Math.floor(value.length * 6 / 8);
3219
+ const output = new Uint8Array(expectedByteCount);
3220
+ let outputIndex = 0;
3221
+ let accumulator = 0;
3222
+ let bitCount = 0;
3223
+ for (const character of value) {
3224
+ const sextet = BASE64URL_ALPHABET.indexOf(character);
3225
+ if (sextet < 0) {
3226
+ return void 0;
3227
+ }
3228
+ accumulator = accumulator << 6 | sextet;
3229
+ bitCount += 6;
3230
+ while (bitCount >= 8) {
3231
+ bitCount -= 8;
3232
+ output[outputIndex] = accumulator >> bitCount & 255;
3233
+ outputIndex += 1;
3234
+ accumulator &= (1 << bitCount) - 1;
3235
+ }
3236
+ }
3237
+ if (outputIndex !== expectedByteCount || bitCount > 0 && accumulator !== 0) {
3238
+ return void 0;
3239
+ }
3240
+ return output;
3241
+ }
3242
+ function decodeCanonicalEndpointDeltas(bytes, endpointCount) {
3243
+ if (!isBoundedPositiveInteger(
3244
+ endpointCount,
3245
+ MAX_PROFILE_ENDPOINT_COUNT
3246
+ ) || endpointCount % 2 !== 0) {
3247
+ return void 0;
3248
+ }
3249
+ const endpoints = new Uint32Array(endpointCount);
3250
+ let byteOffset = 0;
3251
+ let previousEndpoint = 0;
3252
+ for (let endpointIndex = 0; endpointIndex < endpointCount; endpointIndex += 1) {
3253
+ let delta = 0;
3254
+ let multiplier = 1;
3255
+ let byteCount = 0;
3256
+ while (true) {
3257
+ if (byteOffset >= bytes.length || byteCount >= MAX_ULEB128_BYTES) {
3258
+ return void 0;
3259
+ }
3260
+ const byte = bytes[byteOffset];
3261
+ if (byte === void 0) {
3262
+ return void 0;
3263
+ }
3264
+ byteOffset += 1;
3265
+ byteCount += 1;
3266
+ const payload = byte & 127;
3267
+ delta += payload * multiplier;
3268
+ if (!Number.isSafeInteger(delta)) {
3269
+ return void 0;
3270
+ }
3271
+ if ((byte & 128) === 0) {
3272
+ if (byteCount > 1 && payload === 0) {
3273
+ return void 0;
3274
+ }
3275
+ break;
3276
+ }
3277
+ multiplier *= 128;
3278
+ }
3279
+ const endpoint = previousEndpoint + delta;
3280
+ if (delta <= 0 || !Number.isSafeInteger(endpoint) || endpoint > MAX_UNICODE_ENDPOINT) {
3281
+ return void 0;
3282
+ }
3283
+ endpoints[endpointIndex] = endpoint;
3284
+ previousEndpoint = endpoint;
3285
+ }
3286
+ if (byteOffset !== bytes.length) {
3287
+ return void 0;
3288
+ }
3289
+ return endpoints;
3290
+ }
3291
+ function hasExpectedRanges(endpoints, expected) {
3292
+ let previousEnd = -1;
3293
+ let codePointCount = 0;
3294
+ for (let index = 0; index < endpoints.length; index += 2) {
3295
+ const start = endpoints[index];
3296
+ const end = endpoints[index + 1];
3297
+ if (start === void 0 || end === void 0 || start <= previousEnd || end <= start || end > MAX_UNICODE_ENDPOINT) {
3298
+ return false;
3299
+ }
3300
+ codePointCount += end - start;
3301
+ previousEnd = end;
3302
+ }
3303
+ return codePointCount === expected.codePointCount;
3304
+ }
3305
+ function decodeFeedbackUnicodeProfileArtifact(value, expected) {
3306
+ if (!isRecord(value) || !hasBoundedCounts(value, expected) || !hasExpectedMetadata(value, expected) || typeof value.payload !== "string") {
3307
+ return void 0;
3308
+ }
3309
+ const bytes = decodeCanonicalBase64Url(value.payload);
3310
+ if (bytes === void 0) {
3311
+ return void 0;
3312
+ }
3313
+ const endpoints = decodeCanonicalEndpointDeltas(
3314
+ bytes,
3315
+ expected.endpointCount
3316
+ );
3317
+ return endpoints !== void 0 && hasExpectedRanges(endpoints, expected) ? endpoints : void 0;
3318
+ }
3319
+
3320
+ // src/feedback-unicode-profile.ts
3321
+ var FEEDBACK_UNICODE_PROFILE_ID = "unicode-15.1.0-nfkc-v1";
3322
+ var FEEDBACK_UNICODE_PROFILE_ENDPOINT_SHA256 = "591e457524d6b4b988aa7c7687e76c95a78370fea38bbd1b09085be7fd935ef3";
3323
+ var MAX_UNICODE_CODE_POINT = 1114111;
3324
+ var HIGH_SURROGATE_START = 55296;
3325
+ var HIGH_SURROGATE_END = 56319;
3326
+ var LOW_SURROGATE_START = 56320;
3327
+ var LOW_SURROGATE_END = 57343;
3328
+ var UNASSIGNED_RANGE_ENDPOINTS = decodeFeedbackUnicodeProfileArtifact(
3329
+ feedback_unicode_15_1_0_unassigned_default,
3330
+ {
3331
+ profileId: FEEDBACK_UNICODE_PROFILE_ID,
3332
+ unicodeVersion: "15.1.0",
3333
+ sourcePackage: "@unicode/unicode-15.1.0",
3334
+ sourcePackageVersion: "1.6.17",
3335
+ sourceProperty: "General_Category/Unassigned",
3336
+ rangeEncoding: "flat-half-open-delta-uleb128-base64url-v1",
3337
+ rangeCount: 707,
3338
+ endpointCount: 1414,
3339
+ codePointCount: 824718,
3340
+ endpointSha256: FEEDBACK_UNICODE_PROFILE_ENDPOINT_SHA256
3341
+ }
3342
+ );
3343
+ function isFeedbackUnicodeProfileUnassigned(codePoint) {
3344
+ if (UNASSIGNED_RANGE_ENDPOINTS === void 0 || !Number.isInteger(codePoint) || codePoint < 0 || codePoint > MAX_UNICODE_CODE_POINT || codePoint >= HIGH_SURROGATE_START && codePoint <= LOW_SURROGATE_END) {
3345
+ return true;
3346
+ }
3347
+ let lowerRange = 0;
3348
+ let upperRange = UNASSIGNED_RANGE_ENDPOINTS.length / 2 - 1;
3349
+ while (lowerRange <= upperRange) {
3350
+ const rangeIndex = Math.floor((lowerRange + upperRange) / 2);
3351
+ const start = UNASSIGNED_RANGE_ENDPOINTS[rangeIndex * 2];
3352
+ const end = UNASSIGNED_RANGE_ENDPOINTS[rangeIndex * 2 + 1];
3353
+ if (start === void 0 || end === void 0) {
3354
+ return true;
3355
+ }
3356
+ if (codePoint < start) {
3357
+ upperRange = rangeIndex - 1;
3358
+ } else if (codePoint >= end) {
3359
+ lowerRange = rangeIndex + 1;
3360
+ } else {
3361
+ return true;
3362
+ }
3363
+ }
3364
+ return false;
3365
+ }
3366
+ function containsFeedbackUnicodeProfileUnsupportedText(text) {
3367
+ if (typeof text !== "string") {
3368
+ return true;
3369
+ }
3370
+ for (let index = 0; index < text.length; index += 1) {
3371
+ const first = text.charCodeAt(index);
3372
+ let codePoint = first;
3373
+ if (first >= HIGH_SURROGATE_START && first <= HIGH_SURROGATE_END) {
3374
+ const second = text.charCodeAt(index + 1);
3375
+ if (!Number.isInteger(second) || second < LOW_SURROGATE_START || second > LOW_SURROGATE_END) {
3376
+ return true;
3377
+ }
3378
+ codePoint = 65536 + (first - HIGH_SURROGATE_START << 10) + (second - LOW_SURROGATE_START);
3379
+ index += 1;
3380
+ } else if (first >= LOW_SURROGATE_START && first <= LOW_SURROGATE_END) {
3381
+ return true;
3382
+ }
3383
+ if (isFeedbackUnicodeProfileUnassigned(codePoint)) {
3384
+ return true;
3385
+ }
3386
+ }
3387
+ return false;
3388
+ }
3389
+
3390
+ // src/feedback.ts
3391
+ var FEEDBACK_UNICODE_NORMALIZATION_PROFILE = FEEDBACK_UNICODE_PROFILE_ID;
3392
+ var FEEDBACK_BUG_COOLDOWN_SECONDS = Object.freeze([
3393
+ 5 * 60,
3394
+ 15 * 60,
3395
+ 60 * 60,
3396
+ 6 * 60 * 60,
3397
+ 24 * 60 * 60
3398
+ ]);
3399
+ var FEEDBACK_REVIEW_COOLDOWN_SECONDS = 30 * 24 * 60 * 60;
3400
+ var FEEDBACK_ISSUE_TYPES = [
3401
+ "visual-layout",
3402
+ "functionality",
3403
+ "gameplay",
3404
+ "performance-stability",
3405
+ "accessibility",
3406
+ "content-localisation",
3407
+ "account-access",
3408
+ "privacy-security",
3409
+ "other"
3410
+ ];
3411
+ var FEEDBACK_PERSISTABLE_ISSUE_TYPES = FEEDBACK_ISSUE_TYPES.filter(
3412
+ (issueType) => issueType !== "privacy-security"
3413
+ );
3414
+ var FEEDBACK_SEVERITY_LEVELS = [
3415
+ { value: 1, id: "cosmetic", labelKey: "feedback.severity.cosmetic" },
3416
+ { value: 2, id: "minor", labelKey: "feedback.severity.minor" },
3417
+ { value: 3, id: "disruptive", labelKey: "feedback.severity.disruptive" },
3418
+ { value: 4, id: "blocking", labelKey: "feedback.severity.blocking" },
3419
+ { value: 5, id: "critical", labelKey: "feedback.severity.critical" }
3420
+ ];
3421
+ var FEEDBACK_SATISFACTION_LEVELS = [
3422
+ { value: 1, id: "very-poor", labelKey: "feedback.satisfaction.very-poor" },
3423
+ { value: 2, id: "poor", labelKey: "feedback.satisfaction.poor" },
3424
+ { value: 3, id: "fair", labelKey: "feedback.satisfaction.fair" },
3425
+ { value: 4, id: "good", labelKey: "feedback.satisfaction.good" },
3426
+ { value: 5, id: "excellent", labelKey: "feedback.satisfaction.excellent" }
3427
+ ];
3428
+ var FEEDBACK_SENTIMENT_BUCKETS = [
3429
+ "very-negative",
3430
+ "negative",
3431
+ "mixed",
3432
+ "neutral",
3433
+ "positive",
3434
+ "very-positive",
3435
+ "not-detected"
3436
+ ];
3437
+ var FEEDBACK_INTENT_IDS = [
3438
+ "visual-layout",
3439
+ "functionality",
3440
+ "gameplay",
3441
+ "performance-stability",
3442
+ "accessibility",
3443
+ "content-localisation",
3444
+ "account-access",
3445
+ "other",
3446
+ "praise",
3447
+ "suggestion",
3448
+ "confusion",
3449
+ "frustration"
3450
+ ];
3451
+ var FEEDBACK_THEME_IDS = [
3452
+ "navigation",
3453
+ "visual-design",
3454
+ "game-controls",
3455
+ "rendering",
3456
+ "responsiveness",
3457
+ "stability",
3458
+ "accessibility",
3459
+ "localisation",
3460
+ "account-access",
3461
+ "overall-experience",
3462
+ "other"
3463
+ ];
3464
+ var FEEDBACK_SURFACE_IDS = [
3465
+ "site.about",
3466
+ "admin.analytics",
3467
+ "admin.capabilities",
3468
+ "admin.feature-flags",
3469
+ "admin.feedback",
3470
+ "admin.moderation",
3471
+ "admin.users",
3472
+ "site.chatbot",
3473
+ "site.generator",
3474
+ "site.gpu-demo",
3475
+ "site.home",
3476
+ "game.player-system",
3477
+ "account.profile",
3478
+ "site.video"
3479
+ ];
3480
+ var FEEDBACK_SURFACE_DEFINITIONS = [
3481
+ {
3482
+ id: "site.about",
3483
+ labelKey: "feedback.surface.about",
3484
+ kind: "public",
3485
+ gameDiagnosticsEligible: false
3486
+ },
3487
+ {
3488
+ id: "admin.analytics",
3489
+ labelKey: "feedback.surface.adminAnalytics",
3490
+ kind: "admin",
3491
+ gameDiagnosticsEligible: false
3492
+ },
3493
+ {
3494
+ id: "admin.capabilities",
3495
+ labelKey: "feedback.surface.adminCapabilities",
3496
+ kind: "admin",
3497
+ gameDiagnosticsEligible: false
3498
+ },
3499
+ {
3500
+ id: "admin.feature-flags",
3501
+ labelKey: "feedback.surface.adminFeatureFlags",
3502
+ kind: "admin",
3503
+ gameDiagnosticsEligible: false
3504
+ },
3505
+ {
3506
+ id: "admin.feedback",
3507
+ labelKey: "feedback.surface.adminFeedback",
3508
+ kind: "admin",
3509
+ gameDiagnosticsEligible: false
3510
+ },
3511
+ {
3512
+ id: "admin.moderation",
3513
+ labelKey: "feedback.surface.adminModeration",
3514
+ kind: "admin",
3515
+ gameDiagnosticsEligible: false
3516
+ },
3517
+ {
3518
+ id: "admin.users",
3519
+ labelKey: "feedback.surface.adminUsers",
3520
+ kind: "admin",
3521
+ gameDiagnosticsEligible: false
3522
+ },
3523
+ {
3524
+ id: "site.chatbot",
3525
+ labelKey: "feedback.surface.chatbot",
3526
+ kind: "public",
3527
+ gameDiagnosticsEligible: false
3528
+ },
3529
+ {
3530
+ id: "site.generator",
3531
+ labelKey: "feedback.surface.generator",
3532
+ kind: "game",
3533
+ gameDiagnosticsEligible: true
3534
+ },
3535
+ {
3536
+ id: "site.gpu-demo",
3537
+ labelKey: "feedback.surface.gpuDemo",
3538
+ kind: "game",
3539
+ gameDiagnosticsEligible: true
3540
+ },
3541
+ {
3542
+ id: "site.home",
3543
+ labelKey: "feedback.surface.home",
3544
+ kind: "public",
3545
+ gameDiagnosticsEligible: false
3546
+ },
3547
+ {
3548
+ id: "game.player-system",
3549
+ labelKey: "feedback.surface.playerSystem",
3550
+ kind: "game",
3551
+ gameDiagnosticsEligible: false
3552
+ },
3553
+ {
3554
+ id: "account.profile",
3555
+ labelKey: "feedback.surface.profile",
3556
+ kind: "authenticated",
3557
+ gameDiagnosticsEligible: false
3558
+ },
3559
+ {
3560
+ id: "site.video",
3561
+ labelKey: "feedback.surface.video",
3562
+ kind: "public",
3563
+ gameDiagnosticsEligible: false
3564
+ }
3565
+ ];
3566
+ var FEEDBACK_STRUCTURED_ONLY_REASON_CODES = [
3567
+ "analysis-unavailable",
3568
+ "invalid-envelope",
3569
+ "invalid-sensitive-payload",
3570
+ "language-not-enabled",
3571
+ "request-too-large",
3572
+ "length-required"
3573
+ ];
3574
+ var FEEDBACK_PRIVACY_POLICY_VERSIONS = [
3575
+ "feedback-privacy-en-v1"
3576
+ ];
3577
+ var FEEDBACK_ANALYSIS_MODEL_VERSIONS = [
3578
+ "feedback-en-rules-v1"
3579
+ ];
3580
+ for (const vocabulary of [
3581
+ FEEDBACK_BUG_COOLDOWN_SECONDS,
3582
+ FEEDBACK_ISSUE_TYPES,
3583
+ FEEDBACK_PERSISTABLE_ISSUE_TYPES,
3584
+ FEEDBACK_SEVERITY_LEVELS,
3585
+ FEEDBACK_SATISFACTION_LEVELS,
3586
+ FEEDBACK_SENTIMENT_BUCKETS,
3587
+ FEEDBACK_INTENT_IDS,
3588
+ FEEDBACK_THEME_IDS,
3589
+ FEEDBACK_SURFACE_IDS,
3590
+ FEEDBACK_SURFACE_DEFINITIONS,
3591
+ FEEDBACK_STRUCTURED_ONLY_REASON_CODES,
3592
+ FEEDBACK_PRIVACY_POLICY_VERSIONS,
3593
+ FEEDBACK_ANALYSIS_MODEL_VERSIONS
3594
+ ]) {
3595
+ Object.freeze(vocabulary);
3596
+ }
3597
+ for (const entry of [
3598
+ ...FEEDBACK_SEVERITY_LEVELS,
3599
+ ...FEEDBACK_SATISFACTION_LEVELS,
3600
+ ...FEEDBACK_SURFACE_DEFINITIONS
3601
+ ]) {
3602
+ Object.freeze(entry);
3603
+ }
3604
+ var SAFE_ID_PATTERN = /^[a-z0-9][a-z0-9._:-]*$/i;
3605
+ var INGESTION_KEY_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
3606
+ var BASE64URL_PATTERN2 = /^[A-Za-z0-9_-]+$/;
3607
+ var OPAQUE_UUID_V4_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
3608
+ var DISALLOWED_NARRATIVE_SYNTAX_PATTERN = /<|>|(?:https?|ftp|mailto|javascript|data|blob|file):|\/\/|www\.|\]\s*\(/i;
3609
+ var DISALLOWED_UNICODE_FORMAT_PATTERN = /\p{Cf}/u;
3610
+ var MAX_NARRATIVE_CHARACTERS = 4e3;
3611
+ var MAX_NARRATIVE_UTF16_CODE_UNITS = 8e3;
3612
+ var MAX_COUNT = 1e9;
3613
+ var BASE64URL_ALPHABET2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
3614
+ var BUG_HOUR_WINDOW_PATTERN = /^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])T(?:[01]\d|2[0-3])$/;
3615
+ var REVIEW_DAY_WINDOW_PATTERN = /^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])$/;
3616
+ var RECONCILIATION_WINDOW_PATTERN = /^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])T(?:[01]\d|2[0-3]):(?:[0-5]\d)$/;
3617
+ var strictOptions = {
3618
+ version: FEEDBACK_CONTRACT_VERSION,
3619
+ piiEnforcement: "strict",
3620
+ unknownFields: "reject",
3621
+ identity: "exact"
3622
+ };
3623
+ var uuidField = () => field.string().validator((value) => OPAQUE_UUID_V4_PATTERN.test(value)).description("Opaque UUID generated for the feedback workflow");
3624
+ var draftIdField = () => field.string().validator((value) => OPAQUE_UUID_V4_PATTERN.test(value)).description("Opaque identifier for one short-lived structured draft").PID({
3625
+ classification: "low",
3626
+ action: "none",
3627
+ logHandling: "omit",
3628
+ purpose: "short-lived feedback draft lookup that must never enter logs"
3629
+ });
3630
+ var safeIdField = (maximum = 128) => field.string().min(1).max(maximum).pattern(SAFE_ID_PATTERN);
3631
+ var ingestionKeyIdField = () => field.string().min(1).max(80).pattern(INGESTION_KEY_ID_PATTERN);
3632
+ var decodeCanonicalBase64Url2 = (value) => {
3633
+ if (!BASE64URL_PATTERN2.test(value) || value.length % 4 === 1) {
3634
+ return void 0;
3635
+ }
3636
+ const finalValue = BASE64URL_ALPHABET2.indexOf(value.at(-1) ?? "");
3637
+ if (finalValue < 0 || value.length % 4 === 2 && (finalValue & 15) !== 0 || value.length % 4 === 3 && (finalValue & 3) !== 0) {
3638
+ return void 0;
3639
+ }
3640
+ const output = [];
3641
+ let accumulator = 0;
3642
+ let bitCount = 0;
3643
+ for (const character of value) {
3644
+ const sextet = BASE64URL_ALPHABET2.indexOf(character);
3645
+ if (sextet < 0) {
3646
+ return void 0;
3647
+ }
3648
+ accumulator = accumulator << 6 | sextet;
3649
+ bitCount += 6;
3650
+ while (bitCount >= 8) {
3651
+ bitCount -= 8;
3652
+ output.push(accumulator >> bitCount & 255);
3653
+ accumulator &= (1 << bitCount) - 1;
3654
+ }
3655
+ }
3656
+ return Uint8Array.from(output);
3657
+ };
3658
+ var isCanonicalRsaModulus = (value) => {
3659
+ const bytes = decodeCanonicalBase64Url2(value);
3660
+ return bytes !== void 0 && (bytes.length === 256 || bytes.length === 384 || bytes.length === 512) && (bytes[0] ?? 0) >= 128 && ((bytes.at(-1) ?? 0) & 1) === 1;
3661
+ };
3662
+ var isCanonicalRsaExponent = (value) => {
3663
+ const bytes = decodeCanonicalBase64Url2(value);
3664
+ if (bytes === void 0 || bytes.length < 1 || bytes.length > 4 || bytes[0] === 0) {
3665
+ return false;
3666
+ }
3667
+ const exponent = bytes.reduce(
3668
+ (total, byte) => total * 256 + byte,
3669
+ 0
3670
+ );
3671
+ return exponent >= 3 && exponent % 2 === 1;
3672
+ };
3673
+ var surfaceIdField = () => field.string().enum(FEEDBACK_SURFACE_IDS);
3674
+ var countField = () => field.number().validator((value) => Number.isSafeInteger(value)).min(0).max(MAX_COUNT);
3675
+ var positiveCountField2 = (maximum = MAX_COUNT) => field.number().validator((value) => Number.isSafeInteger(value)).min(1).max(maximum);
3676
+ var redactionCountField = () => field.number().validator((value) => Number.isSafeInteger(value)).min(0).max(MAX_NARRATIVE_CHARACTERS);
3677
+ var revisionField = () => field.number().validator((value) => Number.isSafeInteger(value)).min(0).max(1e6);
3678
+ var ratingField = () => field.number().validator((value) => Number.isInteger(value)).min(1).max(5);
3679
+ var narrativeTextField = () => field.string().validator(
3680
+ (value) => typeof value === "string" && value.length >= 1 && value.length <= MAX_NARRATIVE_UTF16_CODE_UNITS && !containsFeedbackUnicodeProfileUnsupportedText(value) && value.normalize("NFKC") === value && [...value].length <= MAX_NARRATIVE_CHARACTERS && !DISALLOWED_NARRATIVE_SYNTAX_PATTERN.test(value) && !DISALLOWED_UNICODE_FORMAT_PATTERN.test(value) && ![...value].some((character) => {
3681
+ const codePoint = character.codePointAt(0);
3682
+ return codePoint !== void 0 && (codePoint < 32 || codePoint === 127);
3683
+ })
3684
+ ).min(1).max(MAX_NARRATIVE_UTF16_CODE_UNITS).PID({
3685
+ classification: "high",
3686
+ action: "clear",
3687
+ logHandling: "omit",
3688
+ purpose: "transient feedback narrative that must be discarded after classification"
3689
+ });
3690
+ var transientCorrelationIdField = () => field.string().validator((value) => OPAQUE_UUID_V4_PATTERN.test(value)).PID({
3691
+ classification: "low",
3692
+ action: "clear",
3693
+ logHandling: "omit",
3694
+ purpose: "one-use transient feedback correlation"
3695
+ });
3696
+ var transientEncryptedField = (minimum, maximum, allowedLengths) => field.string().min(minimum).max(maximum).pattern(BASE64URL_PATTERN2).validator(
3697
+ (value) => {
3698
+ const decoded = decodeCanonicalBase64Url2(value);
3699
+ return decoded !== void 0 && decoded.length > 0 && (allowedLengths === void 0 || allowedLengths.includes(value.length));
3700
+ }
3701
+ ).PID({
3702
+ classification: "high",
3703
+ action: "clear",
3704
+ logHandling: "omit",
3705
+ purpose: "encrypted transient feedback narrative material"
3706
+ });
3707
+ var richTextNodeShape = () => ({
3708
+ type: field.string().enum(["text"]),
3709
+ text: narrativeTextField(),
3710
+ marks: field.array(
3711
+ field.string().enum(["bold", "italic", "underline"])
3712
+ ).max(3).optional()
3713
+ });
3714
+ var richTextBlockShape = () => ({
3715
+ type: field.string().enum(["paragraph", "listItem"]),
3716
+ depth: field.number().validator((value) => Number.isInteger(value)).min(0).max(4),
3717
+ listType: field.string().enum(["bullet"]).optional(),
3718
+ children: field.array(field.object(richTextNodeShape())).min(1).max(128)
3719
+ });
3720
+ var nestedIdentityShape2 = (type) => ({
3721
+ type: field.string().enum([type]),
3722
+ version: field.string().enum([FEEDBACK_CONTRACT_VERSION])
3723
+ });
3724
+ var envelopeShape = (includeIdentity = false) => ({
3725
+ ...includeIdentity ? nestedIdentityShape2("feedback-encrypted-narrative-envelope") : {},
3726
+ schemaVersion: field.string().enum(["1"]),
3727
+ keyId: ingestionKeyIdField(),
3728
+ algorithm: field.string().enum(["RSA-OAEP-256+A256GCM"]),
3729
+ wrappedKey: transientEncryptedField(342, 683, [342, 512, 683]),
3730
+ iv: transientEncryptedField(16, 16, [16]),
3731
+ ciphertext: transientEncryptedField(2, 49152),
3732
+ authenticationTag: transientEncryptedField(22, 22, [22])
3733
+ });
3734
+ var analysisProjectionShape = (includeIdentity = false) => ({
3735
+ ...includeIdentity ? nestedIdentityShape2("feedback-derived-analysis") : {},
3736
+ status: field.string().enum(["analyzed", "structured-only"]),
3737
+ sentiment: field.string().enum(FEEDBACK_SENTIMENT_BUCKETS).optional(),
3738
+ intentIds: field.array(field.string().enum(FEEDBACK_INTENT_IDS)).max(8),
3739
+ themeIds: field.array(field.string().enum(FEEDBACK_THEME_IDS)).max(8),
3740
+ confidence: field.string().enum(["low", "medium", "high"]).optional(),
3741
+ policyVersion: field.string().enum(FEEDBACK_PRIVACY_POLICY_VERSIONS),
3742
+ modelVersion: field.string().enum(FEEDBACK_ANALYSIS_MODEL_VERSIONS),
3743
+ deterministicRedactionCount: redactionCountField(),
3744
+ scannerRedactionCount: redactionCountField()
3745
+ });
3746
+ var analysisReceiptShape = () => ({
3747
+ receiptId: transientCorrelationIdField(),
3748
+ ...analysisProjectionShape(),
3749
+ analyzedAt: field.dateTimeISO()
3750
+ });
3751
+ var isAnalysisProjectionConsistent = (value) => {
3752
+ const status = value.status;
3753
+ const intentIds = value.intentIds;
3754
+ const themeIds = value.themeIds;
3755
+ if (!Array.isArray(intentIds) || !Array.isArray(themeIds)) {
3756
+ return false;
3757
+ }
3758
+ if (new Set(intentIds).size !== intentIds.length || new Set(themeIds).size !== themeIds.length) {
3759
+ return false;
3760
+ }
3761
+ if (status === "structured-only") {
3762
+ return value.sentiment === void 0 && value.confidence === void 0 && intentIds.length === 0 && themeIds.length === 0;
3763
+ }
3764
+ return status === "analyzed" && value.sentiment !== void 0 && value.confidence !== void 0;
3765
+ };
3766
+ var optionalDraftFields = () => ({
3767
+ surfaceId: surfaceIdField().optional(),
3768
+ issueType: field.string().enum(FEEDBACK_ISSUE_TYPES).optional(),
3769
+ severity: ratingField().optional(),
3770
+ satisfaction: ratingField().optional(),
3771
+ analysisReceiptId: transientCorrelationIdField().optional()
3772
+ });
3773
+ var surfaceEntryShape = () => ({
3774
+ id: surfaceIdField(),
3775
+ labelKey: safeIdField(160),
3776
+ kind: field.string().enum(["public", "authenticated", "admin", "game"]),
3777
+ gameDiagnosticsEligible: field.boolean()
3778
+ });
3779
+ var areSurfacesConsistent = (surfaces) => {
3780
+ if (!Array.isArray(surfaces)) {
3781
+ return false;
3782
+ }
3783
+ const surfaceIds = surfaces.map(
3784
+ (surface) => surface.id
3785
+ );
3786
+ return new Set(surfaceIds).size === surfaceIds.length && surfaces.every(
3787
+ (surface) => {
3788
+ const definition = FEEDBACK_SURFACE_DEFINITIONS.find(
3789
+ ({ id }) => id === surface.id
3790
+ );
3791
+ return definition !== void 0 && surface.labelKey === definition.labelKey && surface.kind === definition.kind && surface.gameDiagnosticsEligible === definition.gameDiagnosticsEligible;
3792
+ }
3793
+ );
3794
+ };
3795
+ var isDraftShapeConsistent = (value) => {
3796
+ const hasDirtyField = value.surfaceId !== void 0 || value.issueType !== void 0 || value.severity !== void 0 || value.satisfaction !== void 0 || value.analysisReceiptId !== void 0 || value.analysis !== void 0;
3797
+ if (!hasDirtyField) {
3798
+ return false;
3799
+ }
3800
+ if (value.kind === "bug") {
3801
+ return value.satisfaction === void 0;
3802
+ }
3803
+ if (value.kind === "review") {
3804
+ return value.surfaceId === void 0 && value.issueType === void 0 && value.severity === void 0;
3805
+ }
3806
+ return false;
3807
+ };
3808
+ var isContextConsistent = (value) => {
3809
+ if (!areSurfacesConsistent(value.surfaces)) {
3810
+ return false;
3811
+ }
3812
+ if (value.selectedSurfaceId !== void 0 && !value.surfaces.some(
3813
+ (surface) => surface.id === value.selectedSurfaceId
3814
+ )) {
3815
+ return false;
3816
+ }
3817
+ const hasProjectedSurface = value.surfaces.length > 0;
3818
+ const hasDiagnosticsSurface = value.surfaces.some(
3819
+ (surface) => surface.gameDiagnosticsEligible === true
3820
+ );
3821
+ if (value.eligibility.bugReport && !hasProjectedSurface || value.eligibility.gameDiagnostics && (!value.eligibility.bugReport || !hasDiagnosticsSurface)) {
3822
+ return false;
3823
+ }
3824
+ const generatedAt = Date.parse(String(value.generatedAt));
3825
+ if (!Number.isFinite(generatedAt)) {
3826
+ return false;
3827
+ }
3828
+ const boundedFutureAvailabilityIsValid = (candidate, maximumSeconds) => {
3829
+ if (candidate === void 0) {
3830
+ return true;
3831
+ }
3832
+ const availableAt = Date.parse(String(candidate));
3833
+ return Number.isFinite(availableAt) && availableAt > generatedAt && availableAt - generatedAt <= maximumSeconds * 1e3;
3834
+ };
3835
+ const maximumBugCooldownSeconds = FEEDBACK_BUG_COOLDOWN_SECONDS[FEEDBACK_BUG_COOLDOWN_SECONDS.length - 1] ?? 0;
3836
+ if (!boundedFutureAvailabilityIsValid(
3837
+ value.eligibility.bugAvailableAt,
3838
+ maximumBugCooldownSeconds
3839
+ ) || !boundedFutureAvailabilityIsValid(
3840
+ value.eligibility.reviewAvailableAt,
3841
+ FEEDBACK_REVIEW_COOLDOWN_SECONDS
3842
+ )) {
3843
+ return false;
3844
+ }
3845
+ const bugAvailableAt = value.eligibility.bugAvailableAt === void 0 ? void 0 : Date.parse(String(value.eligibility.bugAvailableAt));
3846
+ const bugRetryAfterSeconds = value.eligibility.bugRetryAfterSeconds;
3847
+ const bugCooldownIsConsistent = bugAvailableAt === void 0 && bugRetryAfterSeconds === void 0 || bugAvailableAt !== void 0 && typeof bugRetryAfterSeconds === "number" && bugRetryAfterSeconds === Math.ceil((bugAvailableAt - generatedAt) / 1e3);
3848
+ if (!bugCooldownIsConsistent || value.eligibility.bugReport && (value.eligibility.bugAvailableAt !== void 0 || value.eligibility.bugRetryAfterSeconds !== void 0) || value.eligibility.review && value.eligibility.reviewAvailableAt !== void 0 || value.eligibility.bugReport && !value.flags.bugReport || value.eligibility.review && !value.flags.review || value.eligibility.gameDiagnostics && !value.flags.gameDiagnostics) {
3849
+ return false;
3850
+ }
3851
+ if (!value.flags.transientAnalysis) {
3852
+ return value.ingestionKey === void 0;
3853
+ }
3854
+ if (value.ingestionKey === void 0) {
3855
+ return false;
3856
+ }
3857
+ const expiresAt = Date.parse(String(value.ingestionKey.expiresAt));
3858
+ return Number.isFinite(expiresAt) && expiresAt > generatedAt && expiresAt - generatedAt <= 10 * 60 * 1e3;
3859
+ };
3860
+ var distributionShape = (idField = () => safeIdField(128)) => ({
3861
+ id: idField(),
3862
+ count: countField()
3863
+ });
3864
+ var hasUniqueIds = (values) => Array.isArray(values) && new Set(
3865
+ values.map(
3866
+ (value) => typeof value === "object" && value !== null ? value.id : void 0
3867
+ )
3868
+ ).size === values.length;
3869
+ var distributionTotal = (values) => Array.isArray(values) ? values.reduce(
3870
+ (total, value) => total + (typeof value === "object" && value !== null && typeof value.count === "number" ? value.count : 0),
3871
+ 0
3872
+ ) : 0;
3873
+ var distributionCountsAtMost = (values, maximum) => Array.isArray(values) && values.every(
3874
+ (value) => typeof value === "object" && value !== null && typeof value.count === "number" && value.count <= maximum
3875
+ );
3876
+ var advisoryShape = () => ({
3877
+ code: field.string().enum(
3878
+ [
3879
+ "severity-five",
3880
+ "critical-regression",
3881
+ "satisfaction-drop",
3882
+ "processor-stale"
3883
+ ]
3884
+ ),
3885
+ level: field.string().enum(["advisory", "critical"]),
3886
+ triggerCount: positiveCountField2(),
3887
+ recommendationIds: field.array(
3888
+ field.string().enum(
3889
+ [
3890
+ "inspect-release",
3891
+ "verify-renderer-health",
3892
+ "review-top-intents",
3893
+ "verify-processor-health"
3894
+ ]
3895
+ )
3896
+ ).min(1).max(8)
3897
+ });
3898
+ var orderedWindow = (value, durationMilliseconds) => {
3899
+ const start = Date.parse(String(value.windowStart));
3900
+ const end = Date.parse(String(value.windowEnd));
3901
+ const generatedAt = Date.parse(String(value.generatedAt));
3902
+ return Number.isFinite(start) && Number.isFinite(end) && Number.isFinite(generatedAt) && new Date(start).toISOString() === value.windowStart && new Date(end).toISOString() === value.windowEnd && start % durationMilliseconds === 0 && end - start === durationMilliseconds && generatedAt >= end;
3903
+ };
3904
+ var processorWindow = (processor, windowKey) => {
3905
+ let iso;
3906
+ let expectedLength;
3907
+ let duration;
3908
+ if (processor === "bug-hourly") {
3909
+ if (!BUG_HOUR_WINDOW_PATTERN.test(windowKey)) {
3910
+ return void 0;
3911
+ }
3912
+ iso = `${windowKey}:00:00.000Z`;
3913
+ expectedLength = 13;
3914
+ duration = 60 * 60 * 1e3;
3915
+ } else if (processor === "review-daily") {
3916
+ if (!REVIEW_DAY_WINDOW_PATTERN.test(windowKey)) {
3917
+ return void 0;
3918
+ }
3919
+ iso = `${windowKey}T00:00:00.000Z`;
3920
+ expectedLength = 10;
3921
+ duration = 24 * 60 * 60 * 1e3;
3922
+ } else {
3923
+ if (!RECONCILIATION_WINDOW_PATTERN.test(windowKey)) {
3924
+ return void 0;
3925
+ }
3926
+ const minute = Number(windowKey.slice(-2));
3927
+ if (minute % 5 !== 0) {
3928
+ return void 0;
3929
+ }
3930
+ iso = `${windowKey}:00.000Z`;
3931
+ expectedLength = 16;
3932
+ duration = 5 * 60 * 1e3;
3933
+ }
3934
+ const start = Date.parse(iso);
3935
+ if (!Number.isFinite(start) || new Date(start).toISOString().slice(0, expectedLength) !== windowKey) {
3936
+ return void 0;
3937
+ }
3938
+ return { start, duration };
3939
+ };
3940
+ var isProcessorArtifactConsistent = (value, artifact) => {
3941
+ const processor = value.processor;
3942
+ const windowKey = String(value.windowKey);
3943
+ const window = processorWindow(processor, windowKey);
3944
+ if (window === void 0) {
3945
+ return false;
3946
+ }
3947
+ const completedAt = Date.parse(
3948
+ String(
3949
+ artifact === "checkpoint" ? value.completedAt : value.generatedAt
3950
+ )
3951
+ );
3952
+ if (!Number.isFinite(completedAt) || completedAt < window.start + window.duration) {
3953
+ return false;
3954
+ }
3955
+ if (artifact === "checkpoint" && value.checkpointId !== `checkpoint:${processor}:${windowKey}`) {
3956
+ return false;
3957
+ }
3958
+ return true;
3959
+ };
3960
+ var roundRate = (value) => Math.round((value + Number.EPSILON) * 1e6) / 1e6;
3961
+ var rateMatches = (actual, expected) => typeof actual === "number" && actual === roundRate(expected);
3962
+ var distributionCountFor = (values, id) => {
3963
+ if (!Array.isArray(values)) {
3964
+ return 0;
3965
+ }
3966
+ const entry = values.find(
3967
+ (value) => typeof value === "object" && value !== null && value.id === id
3968
+ );
3969
+ return typeof entry === "object" && entry !== null && typeof entry.count === "number" ? entry.count : 0;
3970
+ };
3971
+ var advisoryCodesAreConsistent = (advisories, expected) => {
3972
+ if (!Array.isArray(advisories)) {
3973
+ return false;
3974
+ }
3975
+ const expectedCodes = Object.entries(expected).filter(
3976
+ (entry) => entry[1] !== void 0
3977
+ ).map(([code]) => code);
3978
+ const codes = advisories.map(
3979
+ (advisory) => advisory?.code
3980
+ );
3981
+ return new Set(codes).size === codes.length && codes.every(
3982
+ (code) => typeof code === "string" && expectedCodes.includes(code)
3983
+ ) && codes.length === expectedCodes.length && expectedCodes.every((code) => codes.includes(code)) && advisories.every((advisory) => {
3984
+ const value = advisory;
3985
+ const code = typeof value.code === "string" ? value.code : void 0;
3986
+ const expectation = code === void 0 ? void 0 : expected[code];
3987
+ if (expectation === void 0 || value.level !== expectation.level || value.triggerCount !== expectation.triggerCount || !Array.isArray(value.recommendationIds) || value.recommendationIds.length !== expectation.recommendationIds.length) {
3988
+ return false;
3989
+ }
3990
+ return value.recommendationIds.every(
3991
+ (recommendation, index) => recommendation === expectation.recommendationIds[index]
3992
+ );
3993
+ });
3994
+ };
3995
+ var FeedbackRichTextAstSchema = createSchema(
3996
+ {
3997
+ schemaVersion: field.string().enum(["1"]),
3998
+ children: field.array(field.object(richTextBlockShape())).min(1).max(128)
3999
+ },
4000
+ "doc",
4001
+ {
4002
+ ...strictOptions,
4003
+ schemaValidator: (value) => {
4004
+ const blocks = Array.isArray(value.children) ? value.children : [];
4005
+ const blocksAreConsistent = blocks.every(
4006
+ (block) => {
4007
+ const listShapeIsValid = block.type === "paragraph" && block.listType === void 0 || block.type === "listItem" && block.listType === "bullet";
4008
+ const marksAreUnique = Array.isArray(block.children) && block.children.every(
4009
+ (child) => child.marks === void 0 || Array.isArray(child.marks) && new Set(child.marks).size === child.marks.length
4010
+ );
4011
+ return listShapeIsValid && marksAreUnique;
4012
+ }
4013
+ );
4014
+ const characterCount = blocks.reduce(
4015
+ (blockTotal, block) => blockTotal + (Array.isArray(block.children) ? block.children.reduce(
4016
+ (nodeTotal, node) => nodeTotal + (typeof node.text === "string" ? [...node.text].length : 0),
4017
+ 0
4018
+ ) : 0),
4019
+ 0
4020
+ );
4021
+ const extractedCharacterCount = characterCount + Math.max(0, blocks.length - 1);
4022
+ const nodeCount = blocks.reduce(
4023
+ (total, block) => total + (Array.isArray(block.children) ? block.children.length : 0),
4024
+ 0
4025
+ );
4026
+ return value.type === "doc" && value.schemaVersion === "1" && blocksAreConsistent && nodeCount <= 256 && extractedCharacterCount > 0 && extractedCharacterCount <= MAX_NARRATIVE_CHARACTERS;
4027
+ }
4028
+ }
4029
+ );
4030
+ var FeedbackEncryptedNarrativeEnvelopeSchema = createSchema(
4031
+ envelopeShape(),
4032
+ "feedback-encrypted-narrative-envelope",
4033
+ strictOptions
4034
+ );
4035
+ var FeedbackTransientAnalysisRequestSchema = createSchema(
4036
+ {
4037
+ schemaVersion: field.string().enum(["1"]),
4038
+ requestId: transientCorrelationIdField(),
4039
+ purpose: field.string().enum(["bug", "review"]),
4040
+ surfaceId: surfaceIdField().optional(),
4041
+ deterministicRedactionCount: redactionCountField(),
4042
+ envelope: field.object(envelopeShape(true))
4043
+ },
4044
+ "feedback-transient-analysis-request",
4045
+ {
4046
+ ...strictOptions,
4047
+ schemaValidator: (value, context) => {
4048
+ const surfaceWasProvided = context?.wasProvided("surfaceId") ?? Object.prototype.hasOwnProperty.call(value, "surfaceId");
4049
+ return value.purpose === "bug" && value.surfaceId !== void 0 || value.purpose === "review" && !surfaceWasProvided;
4050
+ }
4051
+ }
4052
+ );
4053
+ var validateFeedbackTransientAnalysisRequest = (input) => {
4054
+ const result = FeedbackTransientAnalysisRequestSchema.validate(input);
4055
+ if (!result.valid || result.value === void 0) {
4056
+ return {
4057
+ valid: false,
4058
+ errors: result.errors ?? ["Transient analysis validation failed."],
4059
+ ...result.issues === void 0 ? {} : { issues: result.issues }
4060
+ };
4061
+ }
4062
+ return {
4063
+ valid: true,
4064
+ value: result.value
4065
+ };
4066
+ };
4067
+ var FeedbackAnalysisReceiptSchema = createSchema(
4068
+ analysisReceiptShape(),
4069
+ "feedback-analysis-receipt",
4070
+ {
4071
+ ...strictOptions,
4072
+ schemaValidator: (value) => value.status === "analyzed" && isAnalysisProjectionConsistent(value)
4073
+ }
4074
+ );
4075
+ var FeedbackDerivedAnalysisSchema = createSchema(
4076
+ analysisProjectionShape(),
4077
+ "feedback-derived-analysis",
4078
+ {
4079
+ ...strictOptions,
4080
+ schemaValidator: isAnalysisProjectionConsistent
4081
+ }
4082
+ );
4083
+ var FeedbackSurfaceCatalogSchema = createSchema(
4084
+ {
4085
+ generatedAt: field.dateTimeISO(),
4086
+ catalogVersion: safeIdField(64),
4087
+ surfaces: field.array(field.object(surfaceEntryShape())).max(256)
4088
+ },
4089
+ "feedback-surface-catalog",
4090
+ {
4091
+ ...strictOptions,
4092
+ schemaValidator: (value) => areSurfacesConsistent(value.surfaces)
4093
+ }
4094
+ );
4095
+ var FeedbackContextSchema = createSchema(
4096
+ {
4097
+ generatedAt: field.dateTimeISO(),
4098
+ catalogVersion: safeIdField(64),
4099
+ surfaces: field.array(field.object(surfaceEntryShape())).max(256),
4100
+ selectedSurfaceId: surfaceIdField().optional(),
4101
+ flags: field.object({
4102
+ bugReport: field.boolean(),
4103
+ review: field.boolean(),
4104
+ transientAnalysis: field.boolean(),
4105
+ reporting: field.boolean(),
4106
+ admin: field.boolean(),
4107
+ mcp: field.boolean(),
4108
+ publicHonesty: field.boolean(),
4109
+ gameDiagnostics: field.boolean(),
4110
+ anonymous: field.boolean()
4111
+ }),
4112
+ eligibility: field.object({
4113
+ bugReport: field.boolean(),
4114
+ review: field.boolean(),
4115
+ gameDiagnostics: field.boolean(),
4116
+ bugAvailableAt: field.dateTimeISO().optional(),
4117
+ reviewAvailableAt: field.dateTimeISO().optional(),
4118
+ bugRetryAfterSeconds: positiveCountField2().optional()
4119
+ }),
4120
+ ingestionKey: field.object({
4121
+ keyId: ingestionKeyIdField(),
4122
+ algorithm: field.string().enum(["RSA-OAEP-256"]),
4123
+ publicJwk: field.object({
4124
+ kty: field.string().enum(["RSA"]),
4125
+ alg: field.string().enum(["RSA-OAEP-256"]),
4126
+ use: field.string().enum(["enc"]),
4127
+ key_ops: field.array(field.string().enum(["wrapKey"])).min(1).max(1),
4128
+ n: field.string().min(342).max(683).pattern(BASE64URL_PATTERN2).validator(isCanonicalRsaModulus),
4129
+ e: field.string().min(2).max(6).pattern(BASE64URL_PATTERN2).validator(isCanonicalRsaExponent),
4130
+ ext: field.boolean().validator((value) => value === true)
4131
+ }),
4132
+ expiresAt: field.dateTimeISO()
4133
+ }).optional()
4134
+ },
4135
+ "feedback-context",
4136
+ {
4137
+ ...strictOptions,
4138
+ schemaValidator: isContextConsistent
4139
+ }
4140
+ );
4141
+ var FeedbackDraftUpsertRequestSchema = createSchema(
4142
+ {
4143
+ draftId: draftIdField(),
4144
+ kind: field.string().enum(["bug", "review"]),
4145
+ revision: revisionField(),
4146
+ ...optionalDraftFields()
4147
+ },
4148
+ "feedback-draft-upsert-request",
4149
+ {
4150
+ ...strictOptions,
4151
+ schemaValidator: isDraftShapeConsistent
4152
+ }
4153
+ );
4154
+ var FeedbackDraftPacketSchema = createSchema(
4155
+ {
4156
+ draftId: draftIdField(),
4157
+ kind: field.string().enum(["bug", "review"]),
4158
+ revision: revisionField(),
4159
+ surfaceId: surfaceIdField().optional(),
4160
+ issueType: field.string().enum(FEEDBACK_ISSUE_TYPES).optional(),
4161
+ severity: ratingField().optional(),
4162
+ satisfaction: ratingField().optional(),
4163
+ analysis: field.object(analysisProjectionShape(true)).optional(),
4164
+ serverUpdatedAt: field.dateTimeISO(),
4165
+ expiresAt: field.dateTimeISO()
4166
+ },
4167
+ "feedback-draft-packet",
4168
+ {
4169
+ ...strictOptions,
4170
+ schemaValidator: (value) => {
4171
+ if (!isDraftShapeConsistent(value)) {
4172
+ return false;
4173
+ }
4174
+ if (value.analysis !== void 0 && !isAnalysisProjectionConsistent(value.analysis)) {
4175
+ return false;
4176
+ }
4177
+ const updatedAt = Date.parse(String(value.serverUpdatedAt));
4178
+ const expiresAt = Date.parse(String(value.expiresAt));
4179
+ return Number.isFinite(updatedAt) && Number.isFinite(expiresAt) && expiresAt > updatedAt && expiresAt - updatedAt <= 24 * 60 * 60 * 1e3;
4180
+ }
4181
+ }
4182
+ );
4183
+ var FeedbackDraftReceiptSchema = createSchema(
4184
+ {
4185
+ draftId: draftIdField(),
4186
+ revision: revisionField(),
4187
+ savedAt: field.dateTimeISO(),
4188
+ expiresAt: field.dateTimeISO()
4189
+ },
4190
+ "feedback-draft-receipt",
4191
+ {
4192
+ ...strictOptions,
4193
+ schemaValidator: (value) => {
4194
+ const savedAt = Date.parse(String(value.savedAt));
4195
+ const expiresAt = Date.parse(String(value.expiresAt));
4196
+ return Number.isFinite(savedAt) && Number.isFinite(expiresAt) && expiresAt > savedAt && expiresAt - savedAt <= 24 * 60 * 60 * 1e3;
4197
+ }
4198
+ }
4199
+ );
4200
+ var FeedbackBugSubmissionRequestSchema = createSchema(
4201
+ {
4202
+ draftId: draftIdField().optional(),
4203
+ surfaceId: surfaceIdField(),
4204
+ issueType: field.string().enum(FEEDBACK_ISSUE_TYPES),
4205
+ severity: ratingField(),
4206
+ analysisReceiptId: transientCorrelationIdField().optional(),
4207
+ gameDiagnostics: field.object(feedbackGameDiagnosticsShape(true)).optional()
4208
+ },
4209
+ "feedback-bug-submission-request",
4210
+ {
4211
+ ...strictOptions,
4212
+ schemaValidator: (value) => value.issueType !== "privacy-security" && (value.gameDiagnostics === void 0 || isFeedbackGameDiagnosticsConsistent(value.gameDiagnostics) && value.gameDiagnostics.surfaceId === value.surfaceId)
4213
+ }
4214
+ );
4215
+ var FeedbackReviewSubmissionRequestSchema = createSchema(
4216
+ {
4217
+ draftId: draftIdField().optional(),
4218
+ satisfaction: ratingField(),
4219
+ analysisReceiptId: transientCorrelationIdField().optional()
4220
+ },
4221
+ "feedback-review-submission-request",
4222
+ strictOptions
4223
+ );
4224
+ var FeedbackAcceptanceReceiptSchema = createSchema(
4225
+ {
4226
+ packetId: uuidField(),
4227
+ kind: field.string().enum(["bug", "review"]),
4228
+ acceptedAt: field.dateTimeISO(),
4229
+ nextEligibleAt: field.dateTimeISO()
4230
+ },
4231
+ "feedback-acceptance-receipt",
4232
+ {
4233
+ ...strictOptions,
4234
+ schemaValidator: (value) => {
4235
+ const acceptedAt = Date.parse(String(value.acceptedAt));
4236
+ const nextEligibleAt = Date.parse(String(value.nextEligibleAt));
4237
+ const cooldownMilliseconds = nextEligibleAt - acceptedAt;
4238
+ if (!Number.isFinite(acceptedAt) || !Number.isFinite(nextEligibleAt) || cooldownMilliseconds <= 0 || cooldownMilliseconds % 1e3 !== 0) {
4239
+ return false;
4240
+ }
4241
+ const cooldownSeconds = cooldownMilliseconds / 1e3;
4242
+ return value.kind === "review" ? cooldownSeconds === FEEDBACK_REVIEW_COOLDOWN_SECONDS : FEEDBACK_BUG_COOLDOWN_SECONDS.includes(
4243
+ cooldownSeconds
4244
+ );
4245
+ }
4246
+ }
4247
+ );
4248
+ var FeedbackStructuredOnlyAnalysisResultSchema = createSchema(
4249
+ {
4250
+ status: field.string().enum(["structured-only-required"]),
4251
+ reasonCode: field.string().enum(FEEDBACK_STRUCTURED_ONLY_REASON_CODES)
4252
+ },
4253
+ "feedback-structured-only-analysis-result",
4254
+ strictOptions
4255
+ );
4256
+ var FeedbackBugPacketSchema = createSchema(
4257
+ {
4258
+ packetId: uuidField(),
4259
+ acceptedAt: field.dateTimeISO(),
4260
+ surfaceId: surfaceIdField(),
4261
+ issueType: field.string().enum(FEEDBACK_PERSISTABLE_ISSUE_TYPES),
4262
+ severity: ratingField(),
4263
+ releaseId: safeIdField(128),
4264
+ buildId: safeIdField(128),
4265
+ analysis: field.object(analysisProjectionShape(true)).optional(),
4266
+ gameDiagnostics: field.object(feedbackGameDiagnosticsShape(true)).optional()
4267
+ },
4268
+ "feedback-bug-packet",
4269
+ {
4270
+ ...strictOptions,
4271
+ schemaValidator: (value) => (value.analysis === void 0 || isAnalysisProjectionConsistent(value.analysis)) && (value.gameDiagnostics === void 0 || isFeedbackGameDiagnosticsConsistent(value.gameDiagnostics) && value.gameDiagnostics.surfaceId === value.surfaceId)
4272
+ }
4273
+ );
4274
+ var FeedbackReviewPacketSchema = createSchema(
4275
+ {
4276
+ packetId: uuidField(),
4277
+ acceptedAt: field.dateTimeISO(),
4278
+ satisfaction: ratingField(),
4279
+ analysis: field.object(analysisProjectionShape(true)).optional()
4280
+ },
4281
+ "feedback-review-packet",
4282
+ {
4283
+ ...strictOptions,
4284
+ schemaValidator: (value) => value.analysis === void 0 || isAnalysisProjectionConsistent(value.analysis)
4285
+ }
4286
+ );
4287
+ var FeedbackGameReconstructionManifestSchema = createSchema(
4288
+ {
4289
+ reconstructionId: uuidField(),
4290
+ bugPacketId: uuidField(),
4291
+ createdAt: field.dateTimeISO(),
4292
+ expiresAt: field.dateTimeISO(),
4293
+ curatedAssetSetId: safeIdField(128),
4294
+ noticeKey: safeIdField(160),
4295
+ diagnostics: field.object(feedbackGameDiagnosticsShape(true))
4296
+ },
4297
+ "feedback-game-reconstruction-manifest",
4298
+ {
4299
+ ...strictOptions,
4300
+ schemaValidator: (value) => {
4301
+ const createdAt = Date.parse(String(value.createdAt));
4302
+ const expiresAt = Date.parse(String(value.expiresAt));
4303
+ return isFeedbackGameDiagnosticsConsistent(value.diagnostics) && Number.isFinite(createdAt) && Number.isFinite(expiresAt) && expiresAt > createdAt && expiresAt - createdAt <= 30 * 24 * 60 * 60 * 1e3;
4304
+ }
4305
+ }
4306
+ );
4307
+ var FeedbackHourlyBugReportSchema = createSchema(
4308
+ {
4309
+ reportId: uuidField(),
4310
+ windowStart: field.dateTimeISO(),
4311
+ windowEnd: field.dateTimeISO(),
4312
+ revision: revisionField(),
4313
+ generatedAt: field.dateTimeISO(),
4314
+ acceptedCount: countField(),
4315
+ rejectedCount: countField(),
4316
+ diagnosticsAttachedCount: countField(),
4317
+ deterministicRedactionCount: countField(),
4318
+ scannerRedactionCount: countField(),
4319
+ processorLagSeconds: countField(),
4320
+ rates: field.object({
4321
+ rejectionRate: field.number().min(0).max(1),
4322
+ deterministicRedactionsPerAccepted: field.number().min(0).max(4e3),
4323
+ scannerRedactionsPerAccepted: field.number().min(0).max(4e3)
4324
+ }),
4325
+ traffic: field.object({
4326
+ denominator: countField(),
4327
+ acceptedPerTenThousand: field.number().min(0).max(MAX_COUNT).optional()
4328
+ }),
4329
+ targetDistribution: field.array(field.object(distributionShape(surfaceIdField))).max(256),
4330
+ issueTypeDistribution: field.array(
4331
+ field.object(
4332
+ distributionShape(
4333
+ () => field.string().enum(FEEDBACK_PERSISTABLE_ISSUE_TYPES)
4334
+ )
4335
+ )
4336
+ ).max(FEEDBACK_ISSUE_TYPES.length),
4337
+ severityDistribution: field.array(
4338
+ field.object(
4339
+ distributionShape(
4340
+ () => field.string().enum(["1", "2", "3", "4", "5"])
4341
+ )
4342
+ )
4343
+ ).max(5),
4344
+ intentDistribution: field.array(
4345
+ field.object(
4346
+ distributionShape(
4347
+ () => field.string().enum(FEEDBACK_INTENT_IDS)
4348
+ )
4349
+ )
4350
+ ).max(FEEDBACK_INTENT_IDS.length),
4351
+ buildDistribution: field.array(field.object(distributionShape())).max(128),
4352
+ rendererDistribution: field.array(
4353
+ field.object(
4354
+ distributionShape(
4355
+ () => field.string().enum(FEEDBACK_RENDERER_BUCKETS)
4356
+ )
4357
+ )
4358
+ ).max(FEEDBACK_RENDERER_BUCKETS.length),
4359
+ backendDistribution: field.array(
4360
+ field.object(
4361
+ distributionShape(
4362
+ () => field.string().enum(FEEDBACK_BACKEND_BUCKETS)
4363
+ )
4364
+ )
4365
+ ).max(FEEDBACK_BACKEND_BUCKETS.length),
4366
+ viewportDistribution: field.array(
4367
+ field.object(
4368
+ distributionShape(
4369
+ () => field.string().enum(FEEDBACK_VIEWPORT_BUCKETS)
4370
+ )
4371
+ )
4372
+ ).max(FEEDBACK_VIEWPORT_BUCKETS.length),
4373
+ frameRateDistribution: field.array(
4374
+ field.object(
4375
+ distributionShape(
4376
+ () => field.string().enum(FEEDBACK_FRAME_RATE_BUCKETS)
4377
+ )
4378
+ )
4379
+ ).max(FEEDBACK_FRAME_RATE_BUCKETS.length),
4380
+ frameTimeDistribution: field.array(
4381
+ field.object(
4382
+ distributionShape(
4383
+ () => field.string().enum(FEEDBACK_FRAME_TIME_BUCKETS)
4384
+ )
4385
+ )
4386
+ ).max(FEEDBACK_FRAME_TIME_BUCKETS.length),
4387
+ diagnosticFeatureDistribution: field.array(
4388
+ field.object(
4389
+ distributionShape(
4390
+ () => field.string().enum(FEEDBACK_GAME_FEATURE_IDS)
4391
+ )
4392
+ )
4393
+ ).max(FEEDBACK_GAME_FEATURE_IDS.length),
4394
+ diagnosticCounterDistribution: field.array(
4395
+ field.object(
4396
+ distributionShape(
4397
+ () => field.string().enum(FEEDBACK_GAME_COUNTER_CODES)
4398
+ )
4399
+ )
4400
+ ).max(FEEDBACK_GAME_COUNTER_CODES.length),
4401
+ diagnosticErrorDistribution: field.array(
4402
+ field.object(
4403
+ distributionShape(
4404
+ () => field.string().enum(FEEDBACK_GAME_ERROR_CODES)
4405
+ )
4406
+ )
4407
+ ).max(FEEDBACK_GAME_ERROR_CODES.length),
4408
+ abuseBlockBands: field.array(
4409
+ field.object(
4410
+ distributionShape(
4411
+ () => field.string().enum(
4412
+ [
4413
+ "five-minutes",
4414
+ "fifteen-minutes",
4415
+ "one-hour",
4416
+ "six-hours",
4417
+ "twenty-four-hours",
4418
+ "fail-closed",
4419
+ "edge-blocked"
4420
+ ]
4421
+ )
4422
+ )
4423
+ )
4424
+ ).max(16),
4425
+ comparison: field.object({
4426
+ previousHourRatio: field.number().min(0).max(1e3),
4427
+ sevenDaySameHourRatio: field.number().min(0).max(1e3)
4428
+ }),
4429
+ advisories: field.array(field.object(advisoryShape())).max(32)
4430
+ },
4431
+ "feedback-hourly-bug-report",
4432
+ {
4433
+ ...strictOptions,
4434
+ schemaValidator: (value) => {
4435
+ const distributions = [
4436
+ value.targetDistribution,
4437
+ value.issueTypeDistribution,
4438
+ value.severityDistribution,
4439
+ value.intentDistribution,
4440
+ value.buildDistribution,
4441
+ value.rendererDistribution,
4442
+ value.backendDistribution,
4443
+ value.viewportDistribution,
4444
+ value.frameRateDistribution,
4445
+ value.frameTimeDistribution,
4446
+ value.diagnosticFeatureDistribution,
4447
+ value.diagnosticCounterDistribution,
4448
+ value.diagnosticErrorDistribution,
4449
+ value.abuseBlockBands
4450
+ ];
4451
+ const submittedCount = value.acceptedCount + value.rejectedCount;
4452
+ const expectedRejectionRate = submittedCount === 0 ? 0 : value.rejectedCount / submittedCount;
4453
+ const expectedDeterministicRate = value.acceptedCount === 0 ? 0 : value.deterministicRedactionCount / value.acceptedCount;
4454
+ const expectedScannerRate = value.acceptedCount === 0 ? 0 : value.scannerRedactionCount / value.acceptedCount;
4455
+ const trafficIsConsistent = value.traffic.denominator === 0 && value.traffic.acceptedPerTenThousand === void 0 || value.traffic.denominator > 0 && rateMatches(
4456
+ value.traffic.acceptedPerTenThousand,
4457
+ value.acceptedCount * 1e4 / value.traffic.denominator
4458
+ );
4459
+ const severityFiveCount = distributionCountFor(
4460
+ value.severityDistribution,
4461
+ "5"
4462
+ );
4463
+ const criticalRegression = severityFiveCount >= 3 || value.acceptedCount >= 5 && value.comparison.sevenDaySameHourRatio >= 3;
4464
+ const lagSeconds = Math.floor(
4465
+ (Date.parse(String(value.generatedAt)) - Date.parse(String(value.windowEnd))) / 1e3
4466
+ );
4467
+ return orderedWindow(value, 60 * 60 * 1e3) && value.revision >= 1 && value.processorLagSeconds === lagSeconds && value.diagnosticsAttachedCount <= value.acceptedCount && (value.acceptedCount > 0 || value.deterministicRedactionCount === 0 && value.scannerRedactionCount === 0) && rateMatches(value.rates.rejectionRate, expectedRejectionRate) && rateMatches(
4468
+ value.rates.deterministicRedactionsPerAccepted,
4469
+ expectedDeterministicRate
4470
+ ) && rateMatches(
4471
+ value.rates.scannerRedactionsPerAccepted,
4472
+ expectedScannerRate
4473
+ ) && trafficIsConsistent && distributions.every(hasUniqueIds) && advisoryCodesAreConsistent(value.advisories, {
4474
+ "severity-five": severityFiveCount > 0 ? {
4475
+ level: "advisory",
4476
+ triggerCount: severityFiveCount,
4477
+ recommendationIds: ["inspect-release"]
4478
+ } : void 0,
4479
+ "critical-regression": criticalRegression ? {
4480
+ level: "critical",
4481
+ triggerCount: severityFiveCount >= 3 ? severityFiveCount : value.acceptedCount,
4482
+ recommendationIds: [
4483
+ "inspect-release",
4484
+ "verify-renderer-health"
4485
+ ]
4486
+ } : void 0,
4487
+ "processor-stale": lagSeconds > 10 * 60 ? {
4488
+ level: "critical",
4489
+ triggerCount: lagSeconds,
4490
+ recommendationIds: ["verify-processor-health"]
4491
+ } : void 0
4492
+ }) && distributionTotal(value.targetDistribution) === value.acceptedCount && distributionTotal(value.issueTypeDistribution) === value.acceptedCount && distributionTotal(value.severityDistribution) === value.acceptedCount && distributionCountsAtMost(
4493
+ value.intentDistribution,
4494
+ value.acceptedCount
4495
+ ) && distributionTotal(value.intentDistribution) <= value.acceptedCount * 8 && distributionTotal(value.buildDistribution) === value.acceptedCount && distributionTotal(value.rendererDistribution) === value.diagnosticsAttachedCount && distributionTotal(value.backendDistribution) === value.diagnosticsAttachedCount && distributionTotal(value.viewportDistribution) === value.diagnosticsAttachedCount && distributionTotal(value.frameRateDistribution) === value.diagnosticsAttachedCount && distributionTotal(value.frameTimeDistribution) === value.diagnosticsAttachedCount && distributionTotal(value.diagnosticFeatureDistribution) <= value.diagnosticsAttachedCount * FEEDBACK_GAME_FEATURE_IDS.length && distributionCountsAtMost(
4496
+ value.diagnosticFeatureDistribution,
4497
+ value.diagnosticsAttachedCount
4498
+ ) && distributionTotal(value.diagnosticCounterDistribution) <= value.diagnosticsAttachedCount * FEEDBACK_GAME_COUNTER_CODES.length * 1e4 && distributionCountsAtMost(
4499
+ value.diagnosticCounterDistribution,
4500
+ value.diagnosticsAttachedCount * 1e4
4501
+ ) && distributionTotal(value.diagnosticErrorDistribution) <= value.diagnosticsAttachedCount * FEEDBACK_GAME_ERROR_CODES.length && distributionCountsAtMost(
4502
+ value.diagnosticErrorDistribution,
4503
+ value.diagnosticsAttachedCount
4504
+ );
4505
+ }
4506
+ }
4507
+ );
4508
+ var rollingSatisfactionShape = () => ({
4509
+ period: field.string().enum(["7-days", "30-days", "90-days"]),
4510
+ reviewCount: countField(),
4511
+ meanStars: field.number().min(1).max(5).optional()
4512
+ });
4513
+ var satisfactionStatistics = (distribution, total) => {
4514
+ if (!Array.isArray(distribution) || total <= 0) {
4515
+ return void 0;
4516
+ }
4517
+ const counts = [1, 2, 3, 4, 5].map(
4518
+ (star) => distributionCountFor(distribution, String(star))
4519
+ );
4520
+ const weightedTotal = counts.reduce(
4521
+ (sum, count, index) => sum + count * (index + 1),
4522
+ 0
4523
+ );
4524
+ const valueAtPosition = (position) => {
4525
+ let cumulative = 0;
4526
+ for (let index = 0; index < counts.length; index += 1) {
4527
+ cumulative += counts[index] ?? 0;
4528
+ if (cumulative >= position) {
4529
+ return index + 1;
4530
+ }
4531
+ }
4532
+ return 5;
4533
+ };
4534
+ const lower = valueAtPosition(Math.ceil(total / 2));
4535
+ const upper = valueAtPosition(Math.floor(total / 2) + 1);
4536
+ return {
4537
+ mean: Math.round(weightedTotal / total * 10) / 10,
4538
+ median: (lower + upper) / 2
4539
+ };
4540
+ };
4541
+ var FeedbackDailySatisfactionReportSchema = createSchema(
4542
+ {
4543
+ reportId: uuidField(),
4544
+ windowStart: field.dateTimeISO(),
4545
+ windowEnd: field.dateTimeISO(),
4546
+ revision: revisionField(),
4547
+ generatedAt: field.dateTimeISO(),
4548
+ processorLagSeconds: countField(),
4549
+ acceptedReviewCount: countField(),
4550
+ meanStars: field.number().min(1).max(5).optional(),
4551
+ medianStars: field.number().min(1).max(5).optional(),
4552
+ starDistribution: field.array(
4553
+ field.object(
4554
+ distributionShape(
4555
+ () => field.string().enum(["1", "2", "3", "4", "5"])
4556
+ )
4557
+ )
4558
+ ).max(5),
4559
+ sentimentDistribution: field.array(
4560
+ field.object(
4561
+ distributionShape(
4562
+ () => field.string().enum(FEEDBACK_SENTIMENT_BUCKETS)
4563
+ )
4564
+ )
4565
+ ).max(FEEDBACK_SENTIMENT_BUCKETS.length),
4566
+ intentDistribution: field.array(
4567
+ field.object(
4568
+ distributionShape(
4569
+ () => field.string().enum(FEEDBACK_INTENT_IDS)
4570
+ )
4571
+ )
4572
+ ).max(FEEDBACK_INTENT_IDS.length),
4573
+ rollingWindows: field.array(field.object(rollingSatisfactionShape())).max(3),
4574
+ previousPeriodDeltaStars: field.number().min(-4).max(4).optional(),
4575
+ advisories: field.array(field.object(advisoryShape())).max(32)
4576
+ },
4577
+ "feedback-daily-satisfaction-report",
4578
+ {
4579
+ ...strictOptions,
4580
+ schemaValidator: (value) => {
4581
+ if (!orderedWindow(value, 24 * 60 * 60 * 1e3)) {
4582
+ return false;
4583
+ }
4584
+ if (value.acceptedReviewCount === 0 && (value.meanStars !== void 0 || value.medianStars !== void 0)) {
4585
+ return false;
4586
+ }
4587
+ if (value.acceptedReviewCount > 0 && (value.meanStars === void 0 || value.medianStars === void 0)) {
4588
+ return false;
4589
+ }
4590
+ const distributions = [
4591
+ value.starDistribution,
4592
+ value.sentimentDistribution,
4593
+ value.intentDistribution
4594
+ ];
4595
+ const periods = value.rollingWindows.map(
4596
+ (window) => window.period
4597
+ );
4598
+ const sevenDayWindow = value.rollingWindows.find(
4599
+ (window) => window.period === "7-days"
4600
+ );
4601
+ const thirtyDayWindow = value.rollingWindows.find(
4602
+ (window) => window.period === "30-days"
4603
+ );
4604
+ const ninetyDayWindow = value.rollingWindows.find(
4605
+ (window) => window.period === "90-days"
4606
+ );
4607
+ if (sevenDayWindow === void 0 || thirtyDayWindow === void 0 || ninetyDayWindow === void 0) {
4608
+ return false;
4609
+ }
4610
+ const statistics = satisfactionStatistics(
4611
+ value.starDistribution,
4612
+ value.acceptedReviewCount
4613
+ );
4614
+ const lagSeconds = Math.floor(
4615
+ (Date.parse(String(value.generatedAt)) - Date.parse(String(value.windowEnd))) / 1e3
4616
+ );
4617
+ const satisfactionDrop = sevenDayWindow.reviewCount >= 20 && typeof value.previousPeriodDeltaStars === "number" && value.previousPeriodDeltaStars <= -0.3;
4618
+ return value.revision >= 1 && value.processorLagSeconds === lagSeconds && distributions.every(hasUniqueIds) && distributionTotal(value.starDistribution) === value.acceptedReviewCount && distributionTotal(value.sentimentDistribution) <= value.acceptedReviewCount && distributionCountsAtMost(
4619
+ value.sentimentDistribution,
4620
+ value.acceptedReviewCount
4621
+ ) && distributionTotal(value.intentDistribution) <= value.acceptedReviewCount * 8 && distributionCountsAtMost(
4622
+ value.intentDistribution,
4623
+ value.acceptedReviewCount
4624
+ ) && periods.length === 3 && new Set(periods).size === 3 && (statistics === void 0 && value.meanStars === void 0 && value.medianStars === void 0 || statistics !== void 0 && value.meanStars === statistics.mean && value.medianStars === statistics.median) && advisoryCodesAreConsistent(value.advisories, {
4625
+ "satisfaction-drop": satisfactionDrop ? {
4626
+ level: "advisory",
4627
+ triggerCount: sevenDayWindow.reviewCount,
4628
+ recommendationIds: ["review-top-intents"]
4629
+ } : void 0,
4630
+ "processor-stale": lagSeconds > 2.5 * 60 * 60 ? {
4631
+ level: "critical",
4632
+ triggerCount: lagSeconds,
4633
+ recommendationIds: ["verify-processor-health"]
4634
+ } : void 0
4635
+ }) && value.rollingWindows.every(
4636
+ (window) => window.reviewCount === 0 && window.meanStars === void 0 || window.reviewCount > 0 && window.meanStars !== void 0
4637
+ ) && value.acceptedReviewCount <= sevenDayWindow.reviewCount && sevenDayWindow.reviewCount <= thirtyDayWindow.reviewCount && thirtyDayWindow.reviewCount <= ninetyDayWindow.reviewCount;
4638
+ }
4639
+ }
4640
+ );
4641
+ var publicWeeklyPointShape = () => ({
4642
+ weekStart: field.dateTimeISO(),
4643
+ state: field.string().enum(["published", "suppressed"]),
4644
+ acceptedReviewCount: positiveCountField2().optional(),
4645
+ averageStars: field.number().min(1).max(5).optional()
4646
+ });
4647
+ var publicComparisonShape = () => ({
4648
+ previousAcceptedReviewCount: positiveCountField2(),
4649
+ previousAverageStars: field.number().min(1).max(5),
4650
+ deltaStars: field.number().min(-4).max(4)
4651
+ });
4652
+ var FeedbackPublicSummarySchema = createSchema(
4653
+ {
4654
+ snapshotId: uuidField(),
4655
+ generatedAt: field.dateTimeISO(),
4656
+ asOf: field.dateTimeISO(),
4657
+ freshness: field.string().enum(["fresh", "stale"]),
4658
+ reportAgeSeconds: countField(),
4659
+ rollingWindowDays: field.number().enum([90]),
4660
+ state: field.string().enum(["published", "suppressed"]),
4661
+ acceptedReviewCount: positiveCountField2().optional(),
4662
+ averageStars: field.number().min(1).max(5).optional(),
4663
+ trend: field.string().enum(["up", "flat", "down"]).optional(),
4664
+ comparison: field.object(publicComparisonShape()).optional(),
4665
+ weeklyPoints: field.array(field.object(publicWeeklyPointShape())).min(13).max(13)
4666
+ },
4667
+ "feedback-public-summary",
4668
+ {
4669
+ ...strictOptions,
4670
+ schemaValidator: (value) => {
4671
+ const summaryIsSuppressed = value.state === "suppressed" && value.acceptedReviewCount === void 0 && value.averageStars === void 0 && value.trend === void 0 && value.comparison === void 0;
4672
+ const comparisonDelta = value.comparison === void 0 ? void 0 : roundRate(
4673
+ value.averageStars - value.comparison.previousAverageStars
4674
+ );
4675
+ const expectedTrend = comparisonDelta === void 0 ? void 0 : comparisonDelta >= 0.1 ? "up" : comparisonDelta <= -0.1 ? "down" : "flat";
4676
+ const comparisonIsConsistent = value.comparison === void 0 && value.trend === void 0 || value.comparison !== void 0 && value.comparison.previousAcceptedReviewCount >= 10 && value.comparison.deltaStars === comparisonDelta && value.trend === expectedTrend;
4677
+ const summaryIsPublished = value.state === "published" && typeof value.acceptedReviewCount === "number" && value.acceptedReviewCount >= 10 && typeof value.averageStars === "number" && comparisonIsConsistent;
4678
+ if (!summaryIsSuppressed && !summaryIsPublished) {
4679
+ return false;
4680
+ }
4681
+ const weekStarts = value.weeklyPoints.map(
4682
+ (point) => point.weekStart
4683
+ );
4684
+ const asOf = Date.parse(String(value.asOf));
4685
+ const generatedAt = Date.parse(String(value.generatedAt));
4686
+ if (!Number.isFinite(asOf) || !Number.isFinite(generatedAt) || new Date(asOf).toISOString() !== value.asOf || new Date(asOf).getUTCHours() !== 0 || new Date(asOf).getUTCMinutes() !== 0 || new Date(asOf).getUTCSeconds() !== 0 || new Date(asOf).getUTCMilliseconds() !== 0 || generatedAt < asOf || value.reportAgeSeconds !== Math.floor((generatedAt - asOf) / 1e3)) {
4687
+ return false;
4688
+ }
4689
+ const daysSinceMonday = (new Date(asOf).getUTCDay() + 6) % 7;
4690
+ const lastWeekStart = asOf - daysSinceMonday * 24 * 60 * 60 * 1e3;
4691
+ const weeksAreCanonical = weekStarts.every(
4692
+ (weekStart, index) => Date.parse(weekStart) === lastWeekStart - (12 - index) * 7 * 24 * 60 * 60 * 1e3
4693
+ );
4694
+ return new Set(weekStarts).size === weekStarts.length && weeksAreCanonical && (value.state !== "suppressed" || value.weeklyPoints.every(
4695
+ (point) => point.state === "suppressed"
4696
+ )) && value.weeklyPoints.every(
4697
+ (point) => point.state === "suppressed" && point.acceptedReviewCount === void 0 && point.averageStars === void 0 || point.state === "published" && typeof point.acceptedReviewCount === "number" && point.acceptedReviewCount >= 10 && typeof point.averageStars === "number" && (value.state !== "published" || point.acceptedReviewCount <= value.acceptedReviewCount)
4698
+ );
4699
+ }
4700
+ }
4701
+ );
4702
+ var FeedbackProcessorCheckpointSchema = createSchema(
4703
+ {
4704
+ checkpointId: safeIdField(160),
4705
+ processor: field.string().enum(["bug-hourly", "review-daily", "commit-reconciliation"]),
4706
+ windowKey: safeIdField(160),
4707
+ revision: revisionField(),
4708
+ completedAt: field.dateTimeISO(),
4709
+ reportId: uuidField().optional()
4710
+ },
4711
+ "feedback-processor-checkpoint",
4712
+ {
4713
+ ...strictOptions,
4714
+ schemaValidator: (value) => isProcessorArtifactConsistent(value, "checkpoint") && value.revision >= 1 && (value.processor === "commit-reconciliation" && value.reportId === void 0 || value.processor !== "commit-reconciliation" && value.reportId !== void 0)
4715
+ }
4716
+ );
4717
+ var FeedbackMaterializationManifestSchema = createSchema(
4718
+ {
4719
+ manifestId: uuidField(),
4720
+ processor: field.string().enum(["bug-hourly", "review-daily", "commit-reconciliation"]),
4721
+ windowKey: safeIdField(160),
4722
+ revision: revisionField(),
4723
+ generatedAt: field.dateTimeISO(),
4724
+ sourcePacketCount: countField(),
4725
+ lateArrivalCount: countField(),
4726
+ outputReportId: uuidField().optional(),
4727
+ status: field.string().enum(["published", "corrected", "no-op"])
4728
+ },
4729
+ "feedback-materialization-manifest",
4730
+ {
4731
+ ...strictOptions,
4732
+ schemaValidator: (value) => {
4733
+ if (!isProcessorArtifactConsistent(value, "manifest") || value.lateArrivalCount > value.sourcePacketCount) {
4734
+ return false;
4735
+ }
4736
+ if (value.processor === "commit-reconciliation") {
4737
+ return value.status === "no-op" && value.revision >= 1 && value.outputReportId === void 0 && value.lateArrivalCount === 0;
4738
+ }
4739
+ return value.status === "published" && value.revision === 1 && value.lateArrivalCount === 0 && value.outputReportId !== void 0 || value.status === "corrected" && value.revision >= 2 && value.lateArrivalCount > 0 && value.outputReportId !== void 0;
4740
+ }
4741
+ }
4742
+ );
2681
4743
  // Annotate the CommonJS export names for ESM import in node:
2682
4744
  0 && (module.exports = {
4745
+ FEEDBACK_ANALYSIS_MODEL_VERSIONS,
4746
+ FEEDBACK_BACKEND_BUCKETS,
4747
+ FEEDBACK_BUG_COOLDOWN_SECONDS,
4748
+ FEEDBACK_CONTRACT_VERSION,
4749
+ FEEDBACK_FRAME_RATE_BUCKETS,
4750
+ FEEDBACK_FRAME_TIME_BUCKETS,
4751
+ FEEDBACK_GAME_COUNTER_CODES,
4752
+ FEEDBACK_GAME_COUNTER_MAX_COUNT,
4753
+ FEEDBACK_GAME_COUNTER_MAX_ITEMS,
4754
+ FEEDBACK_GAME_ERROR_CODES,
4755
+ FEEDBACK_GAME_FEATURE_IDS,
4756
+ FEEDBACK_GAME_PROVENANCE_CONTRACTS,
4757
+ FEEDBACK_GAME_PROVENANCE_CONTRACT_IDS,
4758
+ FEEDBACK_GAME_SURFACE_IDS,
4759
+ FEEDBACK_INTENT_IDS,
4760
+ FEEDBACK_ISSUE_TYPES,
4761
+ FEEDBACK_PERSISTABLE_ISSUE_TYPES,
4762
+ FEEDBACK_PRIVACY_POLICY_VERSIONS,
4763
+ FEEDBACK_RENDERER_BUCKETS,
4764
+ FEEDBACK_REVIEW_COOLDOWN_SECONDS,
4765
+ FEEDBACK_SATISFACTION_LEVELS,
4766
+ FEEDBACK_SENTIMENT_BUCKETS,
4767
+ FEEDBACK_SEVERITY_LEVELS,
4768
+ FEEDBACK_STRUCTURED_ONLY_REASON_CODES,
4769
+ FEEDBACK_SURFACE_DEFINITIONS,
4770
+ FEEDBACK_SURFACE_IDS,
4771
+ FEEDBACK_THEME_IDS,
4772
+ FEEDBACK_UNICODE_NORMALIZATION_PROFILE,
4773
+ FEEDBACK_VIEWPORT_BUCKETS,
4774
+ FeedbackAcceptanceReceiptSchema,
4775
+ FeedbackAnalysisReceiptSchema,
4776
+ FeedbackBugPacketSchema,
4777
+ FeedbackBugSubmissionRequestSchema,
4778
+ FeedbackContextSchema,
4779
+ FeedbackDailySatisfactionReportSchema,
4780
+ FeedbackDerivedAnalysisSchema,
4781
+ FeedbackDraftPacketSchema,
4782
+ FeedbackDraftReceiptSchema,
4783
+ FeedbackDraftUpsertRequestSchema,
4784
+ FeedbackEncryptedNarrativeEnvelopeSchema,
4785
+ FeedbackGameDiagnosticsSchema,
4786
+ FeedbackGameReconstructionManifestSchema,
4787
+ FeedbackHourlyBugReportSchema,
4788
+ FeedbackMaterializationManifestSchema,
4789
+ FeedbackProcessorCheckpointSchema,
4790
+ FeedbackPublicSummarySchema,
4791
+ FeedbackReviewPacketSchema,
4792
+ FeedbackReviewSubmissionRequestSchema,
4793
+ FeedbackRichTextAstSchema,
4794
+ FeedbackStructuredOnlyAnalysisResultSchema,
4795
+ FeedbackSurfaceCatalogSchema,
4796
+ FeedbackTransientAnalysisRequestSchema,
2683
4797
  FieldBuilder,
2684
4798
  IsoLanguageCode,
2685
4799
  PLAYER_SYSTEM_ACHIEVEMENT_TIERS,
@@ -2688,6 +4802,8 @@ var PlayerSystemCuratedSnapshotSchema = createSchema(
2688
4802
  PlayerSystemCuratedSnapshotSchema,
2689
4803
  PlayerSystemNormalizedEventBatchSchema,
2690
4804
  PlayerSystemObservedEventBatchSchema,
4805
+ SCHEMA_IDENTITY_POLICIES,
4806
+ SCHEMA_UNKNOWN_FIELDS_POLICIES,
2691
4807
  createComponentSchema,
2692
4808
  createSchema,
2693
4809
  field,
@@ -2710,7 +4826,10 @@ var PlayerSystemCuratedSnapshotSchema = createSchema(
2710
4826
  validateCountryCode,
2711
4827
  validateCurrencyCode,
2712
4828
  validateDateTimeISO,
4829
+ validateDisplayName,
2713
4830
  validateEmail,
4831
+ validateFeedbackGameDiagnostics,
4832
+ validateFeedbackTransientAnalysisRequest,
2714
4833
  validateLanguage,
2715
4834
  validateName,
2716
4835
  validatePercentage,