@plasius/schema 1.2.18 → 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 +207 -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 +2258 -14
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.d.cts +987 -286
  32. package/dist/index.d.ts +987 -286
  33. package/dist/index.js +1532 -2197
  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,8 +20,68 @@ 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,
77
+ PLAYER_SYSTEM_ACHIEVEMENT_TIERS: () => PLAYER_SYSTEM_ACHIEVEMENT_TIERS,
78
+ PLAYER_SYSTEM_ACHIEVEMENT_TRACK_STATUSES: () => PLAYER_SYSTEM_ACHIEVEMENT_TRACK_STATUSES,
79
+ PLAYER_SYSTEM_EVENT_KINDS: () => PLAYER_SYSTEM_EVENT_KINDS,
80
+ PlayerSystemCuratedSnapshotSchema: () => PlayerSystemCuratedSnapshotSchema,
81
+ PlayerSystemNormalizedEventBatchSchema: () => PlayerSystemNormalizedEventBatchSchema,
82
+ PlayerSystemObservedEventBatchSchema: () => PlayerSystemObservedEventBatchSchema,
83
+ SCHEMA_IDENTITY_POLICIES: () => SCHEMA_IDENTITY_POLICIES,
84
+ SCHEMA_UNKNOWN_FIELDS_POLICIES: () => SCHEMA_UNKNOWN_FIELDS_POLICIES,
25
85
  createComponentSchema: () => createComponentSchema,
26
86
  createSchema: () => createSchema,
27
87
  field: () => field,
@@ -44,7 +104,10 @@ __export(index_exports, {
44
104
  validateCountryCode: () => validateCountryCode,
45
105
  validateCurrencyCode: () => validateCurrencyCode,
46
106
  validateDateTimeISO: () => validateDateTimeISO,
107
+ validateDisplayName: () => validateDisplayName,
47
108
  validateEmail: () => validateEmail,
109
+ validateFeedbackGameDiagnostics: () => validateFeedbackGameDiagnostics,
110
+ validateFeedbackTransientAnalysisRequest: () => validateFeedbackTransientAnalysisRequest,
48
111
  validateLanguage: () => validateLanguage,
49
112
  validateName: () => validateName,
50
113
  validatePercentage: () => validatePercentage,
@@ -812,7 +875,7 @@ function validateRichText(value) {
812
875
  }
813
876
 
814
877
  // src/validation/name.OWASP.ts
815
- function validateName(value) {
878
+ function validateNameLike(value, pattern) {
816
879
  if (typeof value !== "string") return false;
817
880
  const trimmed = value.trim();
818
881
  if (trimmed.length === 0) return false;
@@ -821,10 +884,15 @@ function validateName(value) {
821
884
  const cp = ch.codePointAt(0);
822
885
  if (cp >= 0 && cp <= 31 || cp === 127) return false;
823
886
  }
824
- const namePattern = /^[\p{L}\p{M}'\-. ]+$/u;
825
- if (!namePattern.test(trimmed)) return false;
887
+ if (!pattern.test(trimmed)) return false;
826
888
  return true;
827
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
+ }
828
896
 
829
897
  // src/validation/user.MS-GOOGLE-APPLE.ts
830
898
  function validateUserId(value) {
@@ -1216,6 +1284,16 @@ var field = {
1216
1284
  )
1217
1285
  };
1218
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
+
1219
1297
  // src/pii.ts
1220
1298
  function enforcePIIField(parentKey, key, value, def, enforcement = "none", errors, logger) {
1221
1299
  const path = parentKey ? `${parentKey}.${key}` : key;
@@ -1250,6 +1328,9 @@ function prepareForStorage(shape, input, encryptFn, hashFn) {
1250
1328
  if (!isMissing) out[key] = null;
1251
1329
  return;
1252
1330
  }
1331
+ if (isMissing && def.isRequired === false) {
1332
+ return;
1333
+ }
1253
1334
  if (def.type === "object" && def._shape) {
1254
1335
  const obj = {};
1255
1336
  for (const [childKey, childDef] of Object.entries(def._shape)) {
@@ -1295,6 +1376,7 @@ function prepareForRead(shape, stored, decryptFn) {
1295
1376
  const readValue = (def, key, container, ctx = {}) => {
1296
1377
  if (!def) return container?.[key];
1297
1378
  const action = def._pii?.action;
1379
+ const hasValue = container !== void 0 && container !== null && Object.prototype.hasOwnProperty.call(container, key);
1298
1380
  if (action === "encrypt") {
1299
1381
  const enc = container?.[key + "Encrypted"] ?? container?.[`${ctx.parentKey ?? key}Encrypted`];
1300
1382
  return enc === void 0 ? void 0 : decryptFn(enc);
@@ -1305,11 +1387,17 @@ function prepareForRead(shape, stored, decryptFn) {
1305
1387
  }
1306
1388
  if (action === "clear")
1307
1389
  return container?.hasOwnProperty(key) ? null : void 0;
1390
+ if (!hasValue && def.isRequired === false) {
1391
+ return void 0;
1392
+ }
1308
1393
  if (def.type === "object" && def._shape) {
1309
1394
  const obj = {};
1310
1395
  const source = container && Object.prototype.hasOwnProperty.call(container, key) ? container[key] : container ?? {};
1311
1396
  for (const [childKey, childDef] of Object.entries(def._shape)) {
1312
- obj[childKey] = readValue(childDef, childKey, source);
1397
+ const child = readValue(childDef, childKey, source);
1398
+ if (child !== void 0) {
1399
+ obj[childKey] = child;
1400
+ }
1313
1401
  }
1314
1402
  return obj;
1315
1403
  }
@@ -1325,7 +1413,10 @@ function prepareForRead(shape, stored, decryptFn) {
1325
1413
  const refShape = def._shape;
1326
1414
  if (refShape) {
1327
1415
  for (const [childKey, childDef] of Object.entries(refShape)) {
1328
- ref[childKey] = readValue(childDef, childKey, ref);
1416
+ const child = readValue(childDef, childKey, ref);
1417
+ if (child !== void 0) {
1418
+ ref[childKey] = child;
1419
+ }
1329
1420
  }
1330
1421
  }
1331
1422
  return ref;
@@ -1334,13 +1425,19 @@ function prepareForRead(shape, stored, decryptFn) {
1334
1425
  };
1335
1426
  const result = {};
1336
1427
  for (const key in shape) {
1337
- 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
+ }
1338
1432
  }
1339
1433
  return result;
1340
1434
  }
1341
1435
  function sanitizeForLog(shape, data, pseudonymFn) {
1342
1436
  const visit = (def, value, ctx = {}) => {
1343
1437
  if (!def) return void 0;
1438
+ if ((value === void 0 || value === null) && def.isRequired === false) {
1439
+ return void 0;
1440
+ }
1344
1441
  const handling = def._pii?.logHandling;
1345
1442
  if (handling === "omit") return void 0;
1346
1443
  if (handling === "redact") return "[REDACTED]";
@@ -1385,18 +1482,37 @@ function sanitizeForLog(shape, data, pseudonymFn) {
1385
1482
  }
1386
1483
  function getPiiAudit(shape) {
1387
1484
  const piiFields = [];
1388
- for (const key in shape) {
1389
- const def = shape[key];
1390
- if (!def) continue;
1485
+ const visit = (def, path) => {
1486
+ if (!def) return;
1391
1487
  if (def._pii && def._pii.classification !== "none") {
1392
1488
  piiFields.push({
1393
- field: key,
1489
+ field: path,
1394
1490
  classification: def._pii.classification,
1395
1491
  action: def._pii.action,
1396
1492
  logHandling: def._pii.logHandling,
1397
1493
  purpose: def._pii.purpose
1398
1494
  });
1399
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);
1400
1516
  }
1401
1517
  return piiFields;
1402
1518
  }
@@ -1629,9 +1745,7 @@ function validateEnum(parentKey, value, enumValues) {
1629
1745
  if (Array.isArray(value)) {
1630
1746
  const invalid = value.filter((v) => !values.includes(v));
1631
1747
  if (invalid.length > 0) {
1632
- return `Field ${parentKey} contains invalid enum values: ${invalid.join(
1633
- ", "
1634
- )}`;
1748
+ return `Field ${parentKey} must contain only: ${values.join(", ")}`;
1635
1749
  }
1636
1750
  } else {
1637
1751
  if (!values.includes(value)) {
@@ -1665,6 +1779,126 @@ function getValidator(def) {
1665
1779
  function getShape(def) {
1666
1780
  return def?._shape ?? def?.shape ?? void 0;
1667
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
+ }
1668
1902
  function normalizeValidationIssue(path, issue, defaultCode) {
1669
1903
  if (typeof issue === "string") {
1670
1904
  return {
@@ -2125,6 +2359,8 @@ function createSchema(_shape, entityType, options = {
2125
2359
  table: "",
2126
2360
  schemaValidator: () => true,
2127
2361
  piiEnforcement: "none",
2362
+ unknownFields: SCHEMA_UNKNOWN_FIELDS_POLICIES[0],
2363
+ identity: SCHEMA_IDENTITY_POLICIES[0],
2128
2364
  schemaUpgrade: void 0
2129
2365
  }) {
2130
2366
  const systemFields = {
@@ -2151,6 +2387,57 @@ function createSchema(_shape, entityType, options = {
2151
2387
  if (typeof input !== "object" || input === null) {
2152
2388
  return { valid: false, errors: ["Input must be an object"] };
2153
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
+ }
2154
2441
  const working = typeof input === "object" && input !== null ? deepClone(input) : { ...input };
2155
2442
  if (working.type == null) working.type = entityType;
2156
2443
  if (working.version == null) working.version = version;
@@ -2173,6 +2460,19 @@ function createSchema(_shape, entityType, options = {
2173
2460
  working.type = entityType;
2174
2461
  working.version = toVersion;
2175
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
+ }
2176
2476
  for (const key in schema._shape) {
2177
2477
  const def = schema._shape[key];
2178
2478
  let value = working[key];
@@ -2255,7 +2555,11 @@ function createSchema(_shape, entityType, options = {
2255
2555
  }
2256
2556
  if (errors.length === 0 && options.schemaValidator) {
2257
2557
  const castValue = result;
2258
- 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)) {
2259
2563
  errors.push("Schema-level validation failed.");
2260
2564
  }
2261
2565
  }
@@ -2559,10 +2863,1947 @@ function getComponentSchema(type) {
2559
2863
  function getAllComponentSchemas() {
2560
2864
  return Array.from(componentSchemaRegistry.entries());
2561
2865
  }
2866
+
2867
+ // src/player-system-events.ts
2868
+ var PLAYER_SYSTEM_EVENT_KINDS = [
2869
+ "combat",
2870
+ "social",
2871
+ "mission",
2872
+ "crafting",
2873
+ "world"
2874
+ ];
2875
+ var PLAYER_SYSTEM_ACHIEVEMENT_TIERS = [
2876
+ "bronze",
2877
+ "silver",
2878
+ "gold"
2879
+ ];
2880
+ var PLAYER_SYSTEM_ACHIEVEMENT_TRACK_STATUSES = [
2881
+ "tracking",
2882
+ "earned"
2883
+ ];
2884
+ var playerIdField = () => field.string().min(1).max(128).PID({
2885
+ classification: "low",
2886
+ action: "none",
2887
+ logHandling: "pseudonym",
2888
+ purpose: "a stable player-scoped storage identifier"
2889
+ }).description(
2890
+ "Stable player identifier; the only personal identifier retained in event projections"
2891
+ );
2892
+ var eventIdField = () => field.string().min(1).max(128);
2893
+ var eventKindField = () => field.string().enum(PLAYER_SYSTEM_EVENT_KINDS);
2894
+ var eventTitleField = () => field.generalText().min(1).max(120).description("Player-visible event title");
2895
+ var eventSummaryField = () => field.generalText().min(1).max(320).description("Player-visible event summary");
2896
+ var observedEventFields = (defaultHighlighted = true) => ({
2897
+ id: eventIdField(),
2898
+ playerId: playerIdField(),
2899
+ occurredAt: field.dateTimeISO(),
2900
+ kind: eventKindField(),
2901
+ title: eventTitleField(),
2902
+ summary: eventSummaryField(),
2903
+ highlighted: defaultHighlighted ? field.boolean().default(false) : field.boolean()
2904
+ });
2905
+ var eventHighlightFields = () => ({
2906
+ id: eventIdField(),
2907
+ title: eventTitleField(),
2908
+ summary: eventSummaryField(),
2909
+ occurredAt: field.dateTimeISO(),
2910
+ kind: eventKindField()
2911
+ });
2912
+ var eventEntryFields = () => ({
2913
+ id: eventIdField(),
2914
+ title: eventTitleField(),
2915
+ summary: eventSummaryField(),
2916
+ occurredAt: field.dateTimeISO(),
2917
+ kind: eventKindField(),
2918
+ highlighted: field.boolean()
2919
+ });
2920
+ var achievementFields = () => ({
2921
+ id: eventIdField(),
2922
+ title: eventTitleField(),
2923
+ tier: field.string().enum(PLAYER_SYSTEM_ACHIEVEMENT_TIERS),
2924
+ progressLabel: eventSummaryField(),
2925
+ earnedAt: field.dateTimeISO().optional()
2926
+ });
2927
+ var achievementTrackFields = () => ({
2928
+ id: eventIdField(),
2929
+ title: eventTitleField(),
2930
+ current: field.number().min(0).max(1e3),
2931
+ target: field.number().min(1).max(1e3),
2932
+ status: field.string().enum(PLAYER_SYSTEM_ACHIEVEMENT_TRACK_STATUSES)
2933
+ });
2934
+ var PlayerSystemObservedEventBatchSchema = createSchema(
2935
+ {
2936
+ source: field.string().min(1).max(120),
2937
+ emittedAt: field.dateTimeISO(),
2938
+ events: field.array(field.object(observedEventFields()))
2939
+ },
2940
+ "player-system-observed-event-batch",
2941
+ {
2942
+ version: "1.0.0",
2943
+ piiEnforcement: "strict"
2944
+ }
2945
+ );
2946
+ var PlayerSystemNormalizedEventBatchSchema = createSchema(
2947
+ {
2948
+ sourceBlobName: field.string().min(1).max(512),
2949
+ processedAt: field.dateTimeISO(),
2950
+ events: field.array(
2951
+ field.object({
2952
+ ...observedEventFields(false),
2953
+ deterministicKey: field.string().min(1).max(256)
2954
+ })
2955
+ )
2956
+ },
2957
+ "player-system-normalized-event-batch",
2958
+ {
2959
+ version: "1.0.0",
2960
+ piiEnforcement: "strict"
2961
+ }
2962
+ );
2963
+ var PlayerSystemCuratedSnapshotSchema = createSchema(
2964
+ {
2965
+ playerId: playerIdField(),
2966
+ projectedAt: field.dateTimeISO(),
2967
+ lastObservedAt: field.dateTimeISO(),
2968
+ highlights: field.array(field.object(eventHighlightFields())),
2969
+ events: field.array(field.object(eventEntryFields())),
2970
+ achievements: field.array(field.object(achievementFields())),
2971
+ tracks: field.array(field.object(achievementTrackFields()))
2972
+ },
2973
+ "player-system-curated-snapshot",
2974
+ {
2975
+ version: "1.0.0",
2976
+ piiEnforcement: "strict"
2977
+ }
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
+ );
2562
4743
  // Annotate the CommonJS export names for ESM import in node:
2563
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,
2564
4797
  FieldBuilder,
2565
4798
  IsoLanguageCode,
4799
+ PLAYER_SYSTEM_ACHIEVEMENT_TIERS,
4800
+ PLAYER_SYSTEM_ACHIEVEMENT_TRACK_STATUSES,
4801
+ PLAYER_SYSTEM_EVENT_KINDS,
4802
+ PlayerSystemCuratedSnapshotSchema,
4803
+ PlayerSystemNormalizedEventBatchSchema,
4804
+ PlayerSystemObservedEventBatchSchema,
4805
+ SCHEMA_IDENTITY_POLICIES,
4806
+ SCHEMA_UNKNOWN_FIELDS_POLICIES,
2566
4807
  createComponentSchema,
2567
4808
  createSchema,
2568
4809
  field,
@@ -2585,7 +4826,10 @@ function getAllComponentSchemas() {
2585
4826
  validateCountryCode,
2586
4827
  validateCurrencyCode,
2587
4828
  validateDateTimeISO,
4829
+ validateDisplayName,
2588
4830
  validateEmail,
4831
+ validateFeedbackGameDiagnostics,
4832
+ validateFeedbackTransientAnalysisRequest,
2589
4833
  validateLanguage,
2590
4834
  validateName,
2591
4835
  validatePercentage,