@plasius/schema 1.4.0 → 1.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -2
- package/dist/{chunk-UQHPDQZX.js → chunk-GNL2RBO5.js} +133 -32
- package/dist/chunk-GNL2RBO5.js.map +1 -0
- package/dist/feedback-diagnostics.cjs +132 -31
- package/dist/feedback-diagnostics.cjs.map +1 -1
- package/dist/feedback-diagnostics.js +1 -1
- package/dist/index.cjs +206 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +62 -1
- package/dist/index.d.ts +62 -1
- package/dist/index.js +72 -13
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-UQHPDQZX.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -20,6 +20,7 @@ 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_ABUSE_BLOCK_BANDS: () => FEEDBACK_ABUSE_BLOCK_BANDS,
|
|
23
24
|
FEEDBACK_ANALYSIS_MODEL_VERSIONS: () => FEEDBACK_ANALYSIS_MODEL_VERSIONS,
|
|
24
25
|
FEEDBACK_BACKEND_BUCKETS: () => FEEDBACK_BACKEND_BUCKETS,
|
|
25
26
|
FEEDBACK_BUG_COOLDOWN_SECONDS: () => FEEDBACK_BUG_COOLDOWN_SECONDS,
|
|
@@ -51,8 +52,10 @@ __export(index_exports, {
|
|
|
51
52
|
FEEDBACK_VIEWPORT_BUCKETS: () => FEEDBACK_VIEWPORT_BUCKETS,
|
|
52
53
|
FeedbackAcceptanceReceiptSchema: () => FeedbackAcceptanceReceiptSchema,
|
|
53
54
|
FeedbackAnalysisReceiptSchema: () => FeedbackAnalysisReceiptSchema,
|
|
55
|
+
FeedbackBugHealthMetricsProjectionSchema: () => FeedbackBugHealthMetricsProjectionSchema,
|
|
54
56
|
FeedbackBugPacketSchema: () => FeedbackBugPacketSchema,
|
|
55
57
|
FeedbackBugSubmissionRequestSchema: () => FeedbackBugSubmissionRequestSchema,
|
|
58
|
+
FeedbackCommittedAcceptanceEvidenceSchema: () => FeedbackCommittedAcceptanceEvidenceSchema,
|
|
56
59
|
FeedbackContextSchema: () => FeedbackContextSchema,
|
|
57
60
|
FeedbackDailySatisfactionReportSchema: () => FeedbackDailySatisfactionReportSchema,
|
|
58
61
|
FeedbackDerivedAnalysisSchema: () => FeedbackDerivedAnalysisSchema,
|
|
@@ -1782,45 +1785,113 @@ function getShape(def) {
|
|
|
1782
1785
|
var MAX_STRICT_VALIDATION_NODES = 1e4;
|
|
1783
1786
|
var MAX_STRICT_VALIDATION_DEPTH = 256;
|
|
1784
1787
|
var MAX_STRICT_VALIDATION_OBJECTS = MAX_STRICT_VALIDATION_NODES;
|
|
1785
|
-
function
|
|
1786
|
-
const
|
|
1787
|
-
|
|
1788
|
-
];
|
|
1788
|
+
function snapshotStrictInput(input) {
|
|
1789
|
+
const snapshot = Array.isArray(input) ? [] : {};
|
|
1790
|
+
const pending = [{ source: input, target: snapshot, depth: 0 }];
|
|
1789
1791
|
const seen = /* @__PURE__ */ new WeakSet();
|
|
1790
|
-
let visitedNodes =
|
|
1792
|
+
let visitedNodes = 1;
|
|
1791
1793
|
try {
|
|
1792
1794
|
while (pending.length > 0) {
|
|
1793
1795
|
const current = pending.pop();
|
|
1794
1796
|
if (!current) {
|
|
1795
1797
|
continue;
|
|
1796
1798
|
}
|
|
1797
|
-
visitedNodes += 1;
|
|
1798
1799
|
if (visitedNodes > MAX_STRICT_VALIDATION_NODES || current.depth > MAX_STRICT_VALIDATION_DEPTH) {
|
|
1799
|
-
return false;
|
|
1800
|
+
return { valid: false };
|
|
1800
1801
|
}
|
|
1801
|
-
if (
|
|
1802
|
-
|
|
1802
|
+
if (seen.has(current.source)) {
|
|
1803
|
+
return { valid: false };
|
|
1803
1804
|
}
|
|
1804
|
-
|
|
1805
|
-
|
|
1805
|
+
seen.add(current.source);
|
|
1806
|
+
const isArray = Array.isArray(current.source);
|
|
1807
|
+
const prototype = Object.getPrototypeOf(current.source);
|
|
1808
|
+
if (isArray && prototype !== Array.prototype || !isArray && prototype !== Object.prototype && prototype !== null) {
|
|
1809
|
+
return { valid: false };
|
|
1806
1810
|
}
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
+
const ownKeys = Reflect.ownKeys(current.source);
|
|
1812
|
+
if (visitedNodes + ownKeys.length > MAX_STRICT_VALIDATION_NODES) {
|
|
1813
|
+
return { valid: false };
|
|
1814
|
+
}
|
|
1815
|
+
const descriptors = /* @__PURE__ */ new Map();
|
|
1816
|
+
for (const key of ownKeys) {
|
|
1817
|
+
const descriptor = Object.getOwnPropertyDescriptor(
|
|
1818
|
+
current.source,
|
|
1819
|
+
key
|
|
1820
|
+
);
|
|
1821
|
+
if (descriptor === void 0) {
|
|
1822
|
+
return { valid: false };
|
|
1823
|
+
}
|
|
1824
|
+
descriptors.set(key, descriptor);
|
|
1811
1825
|
}
|
|
1812
|
-
|
|
1826
|
+
if (isArray) {
|
|
1827
|
+
const lengthDescriptor = descriptors.get("length");
|
|
1828
|
+
if (lengthDescriptor === void 0 || !("value" in lengthDescriptor) || !Number.isSafeInteger(lengthDescriptor.value) || lengthDescriptor.value < 0 || lengthDescriptor.value > MAX_STRICT_VALIDATION_NODES) {
|
|
1829
|
+
return { valid: false };
|
|
1830
|
+
}
|
|
1831
|
+
let elementCount = 0;
|
|
1832
|
+
for (const key of ownKeys) {
|
|
1833
|
+
if (key === "length") {
|
|
1834
|
+
continue;
|
|
1835
|
+
}
|
|
1836
|
+
if (typeof key !== "string" || !/^(?:0|[1-9]\d*)$/.test(key)) {
|
|
1837
|
+
return { valid: false };
|
|
1838
|
+
}
|
|
1839
|
+
const descriptor = descriptors.get(key);
|
|
1840
|
+
if (descriptor === void 0 || descriptor.enumerable !== true || Number(key) >= lengthDescriptor.value) {
|
|
1841
|
+
return { valid: false };
|
|
1842
|
+
}
|
|
1843
|
+
elementCount += 1;
|
|
1844
|
+
}
|
|
1845
|
+
if (elementCount !== lengthDescriptor.value) {
|
|
1846
|
+
return { valid: false };
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
visitedNodes += ownKeys.length;
|
|
1850
|
+
const keys = ownKeys.filter(
|
|
1851
|
+
(key) => descriptors.get(key)?.enumerable
|
|
1852
|
+
);
|
|
1813
1853
|
for (const key of keys) {
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1854
|
+
if (typeof key !== "string") {
|
|
1855
|
+
return { valid: false };
|
|
1856
|
+
}
|
|
1857
|
+
if (isArray && !/^(?:0|[1-9]\d*)$/.test(key)) {
|
|
1858
|
+
return { valid: false };
|
|
1859
|
+
}
|
|
1860
|
+
const descriptor = descriptors.get(key);
|
|
1861
|
+
if (descriptor === void 0 || !("value" in descriptor) || descriptor.get !== void 0 || descriptor.set !== void 0) {
|
|
1862
|
+
return { valid: false };
|
|
1863
|
+
}
|
|
1864
|
+
const child = descriptor.value;
|
|
1865
|
+
if (typeof child === "function") {
|
|
1866
|
+
return { valid: false };
|
|
1867
|
+
}
|
|
1868
|
+
if (typeof child === "object" && child !== null) {
|
|
1869
|
+
const childSnapshot = Array.isArray(child) ? [] : {};
|
|
1870
|
+
Object.defineProperty(current.target, key, {
|
|
1871
|
+
value: childSnapshot,
|
|
1872
|
+
enumerable: true,
|
|
1873
|
+
configurable: true,
|
|
1874
|
+
writable: true
|
|
1875
|
+
});
|
|
1876
|
+
pending.push({
|
|
1877
|
+
source: child,
|
|
1878
|
+
target: childSnapshot,
|
|
1879
|
+
depth: current.depth + 1
|
|
1880
|
+
});
|
|
1881
|
+
continue;
|
|
1882
|
+
}
|
|
1883
|
+
Object.defineProperty(current.target, key, {
|
|
1884
|
+
value: child,
|
|
1885
|
+
enumerable: true,
|
|
1886
|
+
configurable: true,
|
|
1887
|
+
writable: true
|
|
1817
1888
|
});
|
|
1818
1889
|
}
|
|
1819
1890
|
}
|
|
1820
1891
|
} catch {
|
|
1821
|
-
return false;
|
|
1892
|
+
return { valid: false };
|
|
1822
1893
|
}
|
|
1823
|
-
return true;
|
|
1894
|
+
return { valid: true, value: snapshot };
|
|
1824
1895
|
}
|
|
1825
1896
|
function strictReferenceShape(def) {
|
|
1826
1897
|
return {
|
|
@@ -2387,8 +2458,10 @@ function createSchema(_shape, entityType, options = {
|
|
|
2387
2458
|
if (typeof input !== "object" || input === null) {
|
|
2388
2459
|
return { valid: false, errors: ["Input must be an object"] };
|
|
2389
2460
|
}
|
|
2461
|
+
let strictInputSnapshot;
|
|
2390
2462
|
if (options.unknownFields === "reject") {
|
|
2391
|
-
|
|
2463
|
+
const snapshot = snapshotStrictInput(input);
|
|
2464
|
+
if (!snapshot.valid) {
|
|
2392
2465
|
return {
|
|
2393
2466
|
valid: false,
|
|
2394
2467
|
errors: ["Strict validation complexity limit exceeded."],
|
|
@@ -2401,16 +2474,32 @@ function createSchema(_shape, entityType, options = {
|
|
|
2401
2474
|
]
|
|
2402
2475
|
};
|
|
2403
2476
|
}
|
|
2477
|
+
strictInputSnapshot = snapshot.value;
|
|
2404
2478
|
const scanState = {
|
|
2405
2479
|
remainingObjects: MAX_STRICT_VALIDATION_OBJECTS,
|
|
2406
2480
|
limitExceeded: false
|
|
2407
2481
|
};
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2482
|
+
let locations;
|
|
2483
|
+
try {
|
|
2484
|
+
locations = unknownFieldLocations(
|
|
2485
|
+
strictInputSnapshot,
|
|
2486
|
+
schema._shape,
|
|
2487
|
+
"root",
|
|
2488
|
+
scanState
|
|
2489
|
+
);
|
|
2490
|
+
} catch {
|
|
2491
|
+
return {
|
|
2492
|
+
valid: false,
|
|
2493
|
+
errors: ["Strict validation complexity limit exceeded."],
|
|
2494
|
+
issues: [
|
|
2495
|
+
{
|
|
2496
|
+
path: "root",
|
|
2497
|
+
code: "validation_complexity_limit",
|
|
2498
|
+
message: "Strict validation complexity limit exceeded."
|
|
2499
|
+
}
|
|
2500
|
+
]
|
|
2501
|
+
};
|
|
2502
|
+
}
|
|
2414
2503
|
if (scanState.limitExceeded) {
|
|
2415
2504
|
return {
|
|
2416
2505
|
valid: false,
|
|
@@ -2438,7 +2527,23 @@ function createSchema(_shape, entityType, options = {
|
|
|
2438
2527
|
};
|
|
2439
2528
|
}
|
|
2440
2529
|
}
|
|
2441
|
-
|
|
2530
|
+
let working;
|
|
2531
|
+
try {
|
|
2532
|
+
working = strictInputSnapshot ?? (typeof input === "object" && input !== null ? deepClone(input) : { ...input });
|
|
2533
|
+
} catch {
|
|
2534
|
+
return {
|
|
2535
|
+
valid: false,
|
|
2536
|
+
errors: ["Input could not be safely cloned."],
|
|
2537
|
+
issues: [
|
|
2538
|
+
{
|
|
2539
|
+
path: "root",
|
|
2540
|
+
code: "unsafe_input",
|
|
2541
|
+
message: "Input could not be safely cloned."
|
|
2542
|
+
}
|
|
2543
|
+
]
|
|
2544
|
+
};
|
|
2545
|
+
}
|
|
2546
|
+
const providedFieldNames = new Set(Object.keys(working));
|
|
2442
2547
|
if (working.type == null) working.type = entityType;
|
|
2443
2548
|
if (working.version == null) working.version = version;
|
|
2444
2549
|
const fromVersion = String(working.version ?? "0.0.0");
|
|
@@ -2555,9 +2660,8 @@ function createSchema(_shape, entityType, options = {
|
|
|
2555
2660
|
}
|
|
2556
2661
|
if (errors.length === 0 && options.schemaValidator) {
|
|
2557
2662
|
const castValue = result;
|
|
2558
|
-
const source = input;
|
|
2559
2663
|
const validationContext = Object.freeze({
|
|
2560
|
-
wasProvided: (fieldName) =>
|
|
2664
|
+
wasProvided: (fieldName) => providedFieldNames.has(fieldName)
|
|
2561
2665
|
});
|
|
2562
2666
|
if (!options.schemaValidator(castValue, validationContext)) {
|
|
2563
2667
|
errors.push("Schema-level validation failed.");
|
|
@@ -3397,6 +3501,15 @@ var FEEDBACK_BUG_COOLDOWN_SECONDS = Object.freeze([
|
|
|
3397
3501
|
24 * 60 * 60
|
|
3398
3502
|
]);
|
|
3399
3503
|
var FEEDBACK_REVIEW_COOLDOWN_SECONDS = 30 * 24 * 60 * 60;
|
|
3504
|
+
var FEEDBACK_ABUSE_BLOCK_BANDS = Object.freeze([
|
|
3505
|
+
"five-minutes",
|
|
3506
|
+
"fifteen-minutes",
|
|
3507
|
+
"one-hour",
|
|
3508
|
+
"six-hours",
|
|
3509
|
+
"twenty-four-hours",
|
|
3510
|
+
"fail-closed",
|
|
3511
|
+
"edge-blocked"
|
|
3512
|
+
]);
|
|
3400
3513
|
var FEEDBACK_ISSUE_TYPES = [
|
|
3401
3514
|
"visual-layout",
|
|
3402
3515
|
"functionality",
|
|
@@ -3614,6 +3727,7 @@ var BASE64URL_ALPHABET2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0
|
|
|
3614
3727
|
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
3728
|
var REVIEW_DAY_WINDOW_PATTERN = /^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])$/;
|
|
3616
3729
|
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)$/;
|
|
3730
|
+
var CANONICAL_SERVER_UTC_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
|
|
3617
3731
|
var strictOptions = {
|
|
3618
3732
|
version: FEEDBACK_CONTRACT_VERSION,
|
|
3619
3733
|
piiEnforcement: "strict",
|
|
@@ -3621,6 +3735,16 @@ var strictOptions = {
|
|
|
3621
3735
|
identity: "exact"
|
|
3622
3736
|
};
|
|
3623
3737
|
var uuidField = () => field.string().validator((value) => OPAQUE_UUID_V4_PATTERN.test(value)).description("Opaque UUID generated for the feedback workflow");
|
|
3738
|
+
var isCanonicalServerUtc = (value) => {
|
|
3739
|
+
if (typeof value !== "string" || !CANONICAL_SERVER_UTC_PATTERN.test(value)) {
|
|
3740
|
+
return false;
|
|
3741
|
+
}
|
|
3742
|
+
const timestamp = Date.parse(value);
|
|
3743
|
+
return Number.isFinite(timestamp) && new Date(timestamp).toISOString() === value;
|
|
3744
|
+
};
|
|
3745
|
+
var canonicalServerUtcField = () => field.dateTimeISO().validator(isCanonicalServerUtc).description(
|
|
3746
|
+
"Canonical millisecond-precision UTC timestamp supplied by the trusted server"
|
|
3747
|
+
);
|
|
3624
3748
|
var draftIdField = () => field.string().validator((value) => OPAQUE_UUID_V4_PATTERN.test(value)).description("Opaque identifier for one short-lived structured draft").PID({
|
|
3625
3749
|
classification: "low",
|
|
3626
3750
|
action: "none",
|
|
@@ -4284,6 +4408,52 @@ var FeedbackReviewPacketSchema = createSchema(
|
|
|
4284
4408
|
schemaValidator: (value) => value.analysis === void 0 || isAnalysisProjectionConsistent(value.analysis)
|
|
4285
4409
|
}
|
|
4286
4410
|
);
|
|
4411
|
+
var FeedbackCommittedAcceptanceEvidenceSchema = createSchema(
|
|
4412
|
+
{
|
|
4413
|
+
packetId: uuidField(),
|
|
4414
|
+
packetKind: field.string().enum(["bug", "review"]),
|
|
4415
|
+
acceptedAt: canonicalServerUtcField()
|
|
4416
|
+
},
|
|
4417
|
+
"feedback-committed-acceptance-evidence",
|
|
4418
|
+
strictOptions
|
|
4419
|
+
);
|
|
4420
|
+
var FeedbackBugHealthMetricsProjectionSchema = createSchema(
|
|
4421
|
+
{
|
|
4422
|
+
projectionId: uuidField(),
|
|
4423
|
+
windowStart: canonicalServerUtcField(),
|
|
4424
|
+
windowEnd: canonicalServerUtcField(),
|
|
4425
|
+
observedAt: canonicalServerUtcField(),
|
|
4426
|
+
finalized: field.boolean().validator((value) => value === true),
|
|
4427
|
+
rejectedCount: countField(),
|
|
4428
|
+
trafficDenominator: countField(),
|
|
4429
|
+
abuseBlockBands: field.array(
|
|
4430
|
+
field.object({
|
|
4431
|
+
id: field.string().enum(FEEDBACK_ABUSE_BLOCK_BANDS),
|
|
4432
|
+
count: positiveCountField2()
|
|
4433
|
+
})
|
|
4434
|
+
).max(FEEDBACK_ABUSE_BLOCK_BANDS.length)
|
|
4435
|
+
},
|
|
4436
|
+
"feedback-bug-health-metrics-projection",
|
|
4437
|
+
{
|
|
4438
|
+
...strictOptions,
|
|
4439
|
+
schemaValidator: (value) => {
|
|
4440
|
+
const blockBands = value.abuseBlockBands;
|
|
4441
|
+
let previousIndex = -1;
|
|
4442
|
+
const canonicalBands = blockBands.every((bucket) => {
|
|
4443
|
+
const index = FEEDBACK_ABUSE_BLOCK_BANDS.indexOf(bucket.id);
|
|
4444
|
+
if (index <= previousIndex) {
|
|
4445
|
+
return false;
|
|
4446
|
+
}
|
|
4447
|
+
previousIndex = index;
|
|
4448
|
+
return true;
|
|
4449
|
+
});
|
|
4450
|
+
return orderedWindow(
|
|
4451
|
+
{ ...value, generatedAt: value.observedAt },
|
|
4452
|
+
60 * 60 * 1e3
|
|
4453
|
+
) && Date.parse(String(value.observedAt)) >= Date.parse(String(value.windowEnd)) && canonicalBands;
|
|
4454
|
+
}
|
|
4455
|
+
}
|
|
4456
|
+
);
|
|
4287
4457
|
var FeedbackGameReconstructionManifestSchema = createSchema(
|
|
4288
4458
|
{
|
|
4289
4459
|
reconstructionId: uuidField(),
|
|
@@ -4408,20 +4578,10 @@ var FeedbackHourlyBugReportSchema = createSchema(
|
|
|
4408
4578
|
abuseBlockBands: field.array(
|
|
4409
4579
|
field.object(
|
|
4410
4580
|
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
|
-
)
|
|
4581
|
+
() => field.string().enum(FEEDBACK_ABUSE_BLOCK_BANDS)
|
|
4422
4582
|
)
|
|
4423
4583
|
)
|
|
4424
|
-
).max(
|
|
4584
|
+
).max(FEEDBACK_ABUSE_BLOCK_BANDS.length),
|
|
4425
4585
|
comparison: field.object({
|
|
4426
4586
|
previousHourRatio: field.number().min(0).max(1e3),
|
|
4427
4587
|
sevenDaySameHourRatio: field.number().min(0).max(1e3)
|
|
@@ -4742,6 +4902,7 @@ var FeedbackMaterializationManifestSchema = createSchema(
|
|
|
4742
4902
|
);
|
|
4743
4903
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4744
4904
|
0 && (module.exports = {
|
|
4905
|
+
FEEDBACK_ABUSE_BLOCK_BANDS,
|
|
4745
4906
|
FEEDBACK_ANALYSIS_MODEL_VERSIONS,
|
|
4746
4907
|
FEEDBACK_BACKEND_BUCKETS,
|
|
4747
4908
|
FEEDBACK_BUG_COOLDOWN_SECONDS,
|
|
@@ -4773,8 +4934,10 @@ var FeedbackMaterializationManifestSchema = createSchema(
|
|
|
4773
4934
|
FEEDBACK_VIEWPORT_BUCKETS,
|
|
4774
4935
|
FeedbackAcceptanceReceiptSchema,
|
|
4775
4936
|
FeedbackAnalysisReceiptSchema,
|
|
4937
|
+
FeedbackBugHealthMetricsProjectionSchema,
|
|
4776
4938
|
FeedbackBugPacketSchema,
|
|
4777
4939
|
FeedbackBugSubmissionRequestSchema,
|
|
4940
|
+
FeedbackCommittedAcceptanceEvidenceSchema,
|
|
4778
4941
|
FeedbackContextSchema,
|
|
4779
4942
|
FeedbackDailySatisfactionReportSchema,
|
|
4780
4943
|
FeedbackDerivedAnalysisSchema,
|