@adcp/sdk 16.0.0-beta.2 → 16.0.0-beta.4
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 +54 -0
- package/dist/lib/auth/oauth/diagnose.js +3 -11
- package/dist/lib/auth/oauth/diagnose.mjs +4 -12
- package/dist/lib/auth/oauth/diagnostics.d.mts +2 -1
- package/dist/lib/auth/oauth/diagnostics.d.ts +2 -1
- package/dist/lib/auth/oauth/diagnostics.js +8 -10
- package/dist/lib/auth/oauth/diagnostics.mjs +7 -10
- package/dist/lib/core/ConversationTypes.d.mts +8 -3
- package/dist/lib/core/ConversationTypes.d.ts +8 -3
- package/dist/lib/core/SingleAgentClient.d.mts +5 -3
- package/dist/lib/core/SingleAgentClient.d.ts +5 -3
- package/dist/lib/core/TaskExecutor.js +5 -1
- package/dist/lib/core/TaskExecutor.mjs +5 -1
- package/dist/lib/errors/index.d.mts +9 -4
- package/dist/lib/errors/index.d.ts +9 -4
- package/dist/lib/index.d.mts +3 -3
- package/dist/lib/index.d.ts +3 -3
- package/dist/lib/index.js +8 -0
- package/dist/lib/index.mjs +14 -2
- package/dist/lib/negotiation/types.d.mts +20 -39
- package/dist/lib/negotiation/types.d.ts +20 -39
- package/dist/lib/protocols/index.d.mts +60 -24
- package/dist/lib/protocols/index.d.ts +60 -24
- package/dist/lib/protocols/index.js +9 -4
- package/dist/lib/protocols/index.mjs +3 -0
- package/dist/lib/protocols/mcp-modern.js +1 -0
- package/dist/lib/protocols/mcp-modern.mjs +2 -1
- package/dist/lib/protocols/mcp.js +1 -0
- package/dist/lib/protocols/mcp.mjs +2 -1
- package/dist/lib/protocols/responseSizeLimit.d.mts +91 -5
- package/dist/lib/protocols/responseSizeLimit.d.ts +91 -5
- package/dist/lib/protocols/responseSizeLimit.js +195 -31
- package/dist/lib/protocols/responseSizeLimit.mjs +192 -31
- package/dist/lib/reporting/consumer-runtime.js +2 -1
- package/dist/lib/reporting/consumer-runtime.mjs +2 -1
- package/dist/lib/reporting/ledger/handler.js +50 -11
- package/dist/lib/reporting/ledger/handler.mjs +50 -12
- package/dist/lib/reporting/ledger/index.d.mts +17 -14
- package/dist/lib/reporting/ledger/index.d.ts +17 -14
- package/dist/lib/reporting/ledger/index.js +32 -20
- package/dist/lib/reporting/ledger/index.mjs +21 -10
- package/dist/lib/reporting/ledger/offering-validation.d.mts +9 -0
- package/dist/lib/reporting/ledger/offering-validation.d.ts +9 -0
- package/dist/lib/reporting/{gcs/bucket-policy.js → ledger/offering-validation.js} +9 -8
- package/dist/lib/reporting/ledger/offering-validation.mjs +8 -0
- package/dist/lib/reporting/ledger/receipts.d.mts +48 -0
- package/dist/lib/reporting/ledger/receipts.d.ts +48 -0
- package/dist/lib/reporting/ledger/receipts.js +186 -0
- package/dist/lib/reporting/ledger/receipts.mjs +161 -0
- package/dist/lib/reporting/ledger/status-ingest.js +3 -3
- package/dist/lib/reporting/ledger/status-ingest.mjs +4 -5
- package/dist/lib/reporting/ledger/types.d.mts +43 -0
- package/dist/lib/reporting/ledger/types.d.ts +43 -0
- package/dist/lib/reporting/ledger/types.js +31 -2
- package/dist/lib/reporting/ledger/types.mjs +26 -1
- package/dist/lib/reporting/pagination.d.mts +6 -0
- package/dist/lib/reporting/pagination.d.ts +6 -0
- package/dist/lib/reporting/{gcs/errors.js → pagination.js} +12 -17
- package/dist/lib/reporting/pagination.mjs +12 -0
- package/dist/lib/reporting/reconciliation.d.mts +1 -0
- package/dist/lib/reporting/reconciliation.d.ts +1 -0
- package/dist/lib/reporting/reconciliation.js +3 -2
- package/dist/lib/reporting/reconciliation.mjs +3 -2
- package/dist/lib/reporting/service/index.d.mts +79 -153
- package/dist/lib/reporting/service/index.d.ts +79 -153
- package/dist/lib/reporting/service/index.js +34 -491
- package/dist/lib/reporting/service/index.mjs +36 -510
- package/dist/lib/reporting/service/scheduler-support.d.mts +43 -0
- package/dist/lib/reporting/service/scheduler-support.d.ts +43 -0
- package/dist/lib/reporting/service/scheduler-support.js +125 -0
- package/dist/lib/reporting/service/scheduler-support.mjs +96 -0
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/signing/canonicalize.d.mts +4 -0
- package/dist/lib/signing/canonicalize.d.ts +4 -0
- package/dist/lib/signing/canonicalize.js +14 -8
- package/dist/lib/signing/canonicalize.mjs +14 -8
- package/dist/lib/signing/content-digest.d.mts +8 -0
- package/dist/lib/signing/content-digest.d.ts +8 -0
- package/dist/lib/signing/content-digest.js +11 -5
- package/dist/lib/signing/content-digest.mjs +10 -5
- package/dist/lib/signing/crypto.d.mts +15 -0
- package/dist/lib/signing/crypto.d.ts +15 -0
- package/dist/lib/signing/crypto.js +75 -3
- package/dist/lib/signing/crypto.mjs +78 -3
- package/dist/lib/signing/server.d.mts +1 -1
- package/dist/lib/signing/server.d.ts +1 -1
- package/dist/lib/signing/server.js +2 -0
- package/dist/lib/signing/server.mjs +2 -1
- package/dist/lib/signing/signer.js +11 -14
- package/dist/lib/signing/signer.mjs +13 -16
- package/dist/lib/signing/testing.js +2 -6
- package/dist/lib/signing/testing.mjs +3 -7
- package/dist/lib/signing/verifier.js +2 -2
- package/dist/lib/signing/verifier.mjs +3 -3
- package/dist/lib/signing/web-bot-auth.js +122 -43
- package/dist/lib/signing/web-bot-auth.mjs +128 -44
- package/dist/lib/signing/webhook-verifier.js +2 -2
- package/dist/lib/signing/webhook-verifier.mjs +3 -3
- package/dist/lib/substitution/compile.js +2 -1
- package/dist/lib/substitution/compile.mjs +2 -1
- package/dist/lib/substitution/consent-macros.d.mts +4 -0
- package/dist/lib/substitution/consent-macros.d.ts +4 -0
- package/dist/lib/substitution/consent-macros.js +45 -0
- package/dist/lib/substitution/consent-macros.mjs +20 -0
- package/dist/lib/substitution/index.d.mts +1 -1
- package/dist/lib/substitution/index.d.ts +1 -1
- package/dist/lib/substitution/index.js +2 -0
- package/dist/lib/substitution/index.mjs +2 -1
- package/dist/lib/substitution/translate.d.mts +15 -2
- package/dist/lib/substitution/translate.d.ts +15 -2
- package/dist/lib/substitution/translate.js +148 -26
- package/dist/lib/substitution/translate.mjs +147 -26
- package/dist/lib/testing/client.js +2 -1
- package/dist/lib/testing/client.mjs +2 -1
- package/dist/lib/testing/scenarios/capabilities.js +1 -1
- package/dist/lib/testing/scenarios/capabilities.mjs +1 -1
- package/dist/lib/testing/storyboard/junit.js +16 -3
- package/dist/lib/testing/storyboard/junit.mjs +16 -3
- package/dist/lib/testing/storyboard/request-signing/builder.js +12 -14
- package/dist/lib/testing/storyboard/request-signing/builder.mjs +13 -15
- package/dist/lib/testing/storyboard/runner.js +94 -25
- package/dist/lib/testing/storyboard/runner.mjs +94 -25
- package/dist/lib/testing/storyboard/signer-grader/grader.js +2 -7
- package/dist/lib/testing/storyboard/signer-grader/grader.mjs +2 -7
- package/dist/lib/testing/storyboard/types.d.mts +6 -0
- package/dist/lib/testing/storyboard/types.d.ts +6 -0
- package/dist/lib/testing/storyboard/validations.d.mts +1 -1
- package/dist/lib/testing/storyboard/validations.d.ts +1 -1
- package/dist/lib/types/enums.generated.d.mts +3 -0
- package/dist/lib/types/enums.generated.d.ts +3 -0
- package/dist/lib/types/enums.generated.js +9 -0
- package/dist/lib/types/enums.generated.mjs +6 -0
- package/dist/lib/validation/schema-loader.js +25 -0
- package/dist/lib/validation/schema-loader.mjs +24 -0
- package/dist/lib/version.d.mts +3 -3
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/dist/lib/version.mjs +3 -3
- package/docs/TYPE-SUMMARY.md +28 -5
- package/docs/guides/DISCOVERY-CACHE-AND-SESSION-REUSE.md +3 -2
- package/docs/guides/REPORTING-GCS-FENCE.md +3 -3
- package/docs/guides/REPORTING-GCS-MANAGED.md +4 -4
- package/docs/guides/REPORTING-LEDGER-CUTOVER.md +7 -7
- package/docs/guides/REPORTING-LEDGER.md +107 -51
- package/docs/guides/REPORTING-OPERATIONS.md +66 -5
- package/docs/guides/REPORTING-STABILITY.md +36 -32
- package/docs/guides/UNIVERSAL-MACRO-COMPILATION.md +38 -0
- package/docs/guides/VALIDATE-YOUR-AGENT.md +12 -0
- package/docs/llms.txt +4 -3
- package/docs/migration-14.x-rc-worksheet.md +4 -7
- package/docs/migration-reporting-storage-package.md +186 -0
- package/examples/README.md +1 -1
- package/package.json +14 -78
- package/dist/lib/reporting/azure/index.d.mts +0 -31
- package/dist/lib/reporting/azure/index.d.ts +0 -31
- package/dist/lib/reporting/azure/index.js +0 -266
- package/dist/lib/reporting/azure/index.mjs +0 -249
- package/dist/lib/reporting/bigquery/index.d.mts +0 -246
- package/dist/lib/reporting/bigquery/index.d.ts +0 -246
- package/dist/lib/reporting/bigquery/index.js +0 -633
- package/dist/lib/reporting/bigquery/index.mjs +0 -594
- package/dist/lib/reporting/gcs/adapter.d.mts +0 -38
- package/dist/lib/reporting/gcs/adapter.d.ts +0 -38
- package/dist/lib/reporting/gcs/adapter.js +0 -342
- package/dist/lib/reporting/gcs/adapter.mjs +0 -325
- package/dist/lib/reporting/gcs/bucket-policy.d.mts +0 -3
- package/dist/lib/reporting/gcs/bucket-policy.d.ts +0 -3
- package/dist/lib/reporting/gcs/bucket-policy.mjs +0 -7
- package/dist/lib/reporting/gcs/errors.d.mts +0 -11
- package/dist/lib/reporting/gcs/errors.d.ts +0 -11
- package/dist/lib/reporting/gcs/errors.mjs +0 -16
- package/dist/lib/reporting/gcs/fence.d.mts +0 -41
- package/dist/lib/reporting/gcs/fence.d.ts +0 -41
- package/dist/lib/reporting/gcs/fence.js +0 -250
- package/dist/lib/reporting/gcs/fence.mjs +0 -230
- package/dist/lib/reporting/gcs/index.d.mts +0 -18
- package/dist/lib/reporting/gcs/index.d.ts +0 -18
- package/dist/lib/reporting/gcs/index.js +0 -44
- package/dist/lib/reporting/gcs/index.mjs +0 -14
- package/dist/lib/reporting/gcs/io.d.mts +0 -7
- package/dist/lib/reporting/gcs/io.d.ts +0 -7
- package/dist/lib/reporting/gcs/io.js +0 -95
- package/dist/lib/reporting/gcs/io.mjs +0 -69
- package/dist/lib/reporting/gcs/reader.d.mts +0 -67
- package/dist/lib/reporting/gcs/reader.d.ts +0 -67
- package/dist/lib/reporting/gcs/reader.js +0 -193
- package/dist/lib/reporting/gcs/reader.mjs +0 -169
- package/dist/lib/reporting/gcs/row-provider.d.mts +0 -39
- package/dist/lib/reporting/gcs/row-provider.d.ts +0 -39
- package/dist/lib/reporting/gcs/row-provider.js +0 -225
- package/dist/lib/reporting/gcs/row-provider.mjs +0 -208
- package/dist/lib/reporting/gcs/validation.d.mts +0 -5
- package/dist/lib/reporting/gcs/validation.d.ts +0 -5
- package/dist/lib/reporting/gcs/validation.js +0 -49
- package/dist/lib/reporting/gcs/validation.mjs +0 -25
- package/dist/lib/reporting/ledger/change-feed.d.mts +0 -69
- package/dist/lib/reporting/ledger/change-feed.d.ts +0 -69
- package/dist/lib/reporting/ledger/change-feed.js +0 -107
- package/dist/lib/reporting/ledger/change-feed.mjs +0 -80
- package/dist/lib/reporting/ledger/managed-postgres.d.mts +0 -293
- package/dist/lib/reporting/ledger/managed-postgres.d.ts +0 -293
- package/dist/lib/reporting/ledger/managed-postgres.js +0 -2346
- package/dist/lib/reporting/ledger/managed-postgres.mjs +0 -2332
- package/dist/lib/reporting/ledger/managed-router.d.mts +0 -148
- package/dist/lib/reporting/ledger/managed-router.d.ts +0 -148
- package/dist/lib/reporting/ledger/managed-router.js +0 -280
- package/dist/lib/reporting/ledger/managed-router.mjs +0 -258
- package/dist/lib/reporting/ledger/managed.d.mts +0 -535
- package/dist/lib/reporting/ledger/managed.d.ts +0 -535
- package/dist/lib/reporting/ledger/managed.js +0 -761
- package/dist/lib/reporting/ledger/managed.mjs +0 -729
- package/dist/lib/reporting/ledger/notification-activity.d.mts +0 -332
- package/dist/lib/reporting/ledger/notification-activity.d.ts +0 -332
- package/dist/lib/reporting/ledger/notification-activity.js +0 -1366
- package/dist/lib/reporting/ledger/notification-activity.mjs +0 -1337
- package/dist/lib/reporting/ledger/object-writes.d.mts +0 -128
- package/dist/lib/reporting/ledger/object-writes.d.ts +0 -128
- package/dist/lib/reporting/ledger/object-writes.js +0 -147
- package/dist/lib/reporting/ledger/object-writes.mjs +0 -114
- package/dist/lib/reporting/ledger/postgres.d.mts +0 -689
- package/dist/lib/reporting/ledger/postgres.d.ts +0 -689
- package/dist/lib/reporting/ledger/postgres.js +0 -4462
- package/dist/lib/reporting/ledger/postgres.mjs +0 -4462
- package/dist/lib/reporting/ledger/row-storage-migration.d.mts +0 -59
- package/dist/lib/reporting/ledger/row-storage-migration.d.ts +0 -59
- package/dist/lib/reporting/ledger/row-storage-migration.js +0 -365
- package/dist/lib/reporting/ledger/row-storage-migration.mjs +0 -339
- package/dist/lib/reporting/ledger/row-storage-object.d.mts +0 -203
- package/dist/lib/reporting/ledger/row-storage-object.d.ts +0 -203
- package/dist/lib/reporting/ledger/row-storage-object.js +0 -379
- package/dist/lib/reporting/ledger/row-storage-object.mjs +0 -335
- package/dist/lib/reporting/ledger/row-storage-provider-io.d.mts +0 -44
- package/dist/lib/reporting/ledger/row-storage-provider-io.d.ts +0 -44
- package/dist/lib/reporting/ledger/row-storage-provider-io.js +0 -142
- package/dist/lib/reporting/ledger/row-storage-provider-io.mjs +0 -111
- package/dist/lib/reporting/ledger/row-storage.d.mts +0 -316
- package/dist/lib/reporting/ledger/row-storage.d.ts +0 -316
- package/dist/lib/reporting/ledger/row-storage.js +0 -812
- package/dist/lib/reporting/ledger/row-storage.mjs +0 -802
- package/dist/lib/reporting/s3/index.d.mts +0 -34
- package/dist/lib/reporting/s3/index.d.ts +0 -34
- package/dist/lib/reporting/s3/index.js +0 -347
- package/dist/lib/reporting/s3/index.mjs +0 -340
- package/dist/lib/reporting/service/maintenance.d.mts +0 -148
- package/dist/lib/reporting/service/maintenance.d.ts +0 -148
- package/dist/lib/reporting/service/maintenance.js +0 -185
- package/dist/lib/reporting/service/maintenance.mjs +0 -159
- package/examples/reliable-reporting-service/README.md +0 -169
|
@@ -5,52 +5,116 @@ const __dirname = __adcpDirname(__adcpFileURLToPath(import.meta.url));
|
|
|
5
5
|
const require2 = __adcpCreateRequire(import.meta.url);
|
|
6
6
|
import { globalAsyncLocalStorage } from "../utils/global-async-local-storage.mjs";
|
|
7
7
|
import { ResponseTooLargeError } from "../errors/index.mjs";
|
|
8
|
+
import { sanitizeTransportUrl } from "./transportDiagnostics.mjs";
|
|
9
|
+
const DEFAULT_MAX_RESPONSE_BYTES = 4 * 1024 * 1024;
|
|
10
|
+
const SSE_CUMULATIVE_BUDGET_MULTIPLIER = 2;
|
|
8
11
|
const responseSizeLimitStorage = globalAsyncLocalStorage("responseSizeLimit");
|
|
12
|
+
function resolveResponseSizeCap(maxResponseBytes) {
|
|
13
|
+
if (maxResponseBytes === void 0) return DEFAULT_MAX_RESPONSE_BYTES;
|
|
14
|
+
if (maxResponseBytes === 0) return null;
|
|
15
|
+
if (!Number.isFinite(maxResponseBytes) || maxResponseBytes < 0) return DEFAULT_MAX_RESPONSE_BYTES;
|
|
16
|
+
return maxResponseBytes;
|
|
17
|
+
}
|
|
18
|
+
function newSlot(maxResponseBytes) {
|
|
19
|
+
const resolved = resolveResponseSizeCap(maxResponseBytes);
|
|
20
|
+
if (resolved === null) return { maxResponseBytes: null };
|
|
21
|
+
const enclosing = responseSizeLimitStorage.getStore();
|
|
22
|
+
const limit = sseBudgetFor(resolved);
|
|
23
|
+
return {
|
|
24
|
+
// Nesting narrows both numbers. `?? resolved` deliberately also covers an
|
|
25
|
+
// enclosing opt-out (`null`): an inner scope that asks for a cap is the
|
|
26
|
+
// more specific instruction, so it still gets one.
|
|
27
|
+
maxResponseBytes: Math.min(resolved, enclosing?.maxResponseBytes ?? resolved),
|
|
28
|
+
streamLimit: Math.min(limit, enclosing?.streamLimit ?? limit),
|
|
29
|
+
streamMeter: enclosing?.streamMeter ?? { consumed: 0 }
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function sseBudgetFor(maxResponseBytes) {
|
|
33
|
+
return Math.min(maxResponseBytes * SSE_CUMULATIVE_BUDGET_MULTIPLIER, Number.MAX_SAFE_INTEGER);
|
|
34
|
+
}
|
|
35
|
+
function responseSizeCapCacheKey() {
|
|
36
|
+
const slot = responseSizeLimitStorage.getStore();
|
|
37
|
+
const cap = slot ? slot.maxResponseBytes : DEFAULT_MAX_RESPONSE_BYTES;
|
|
38
|
+
return `max-response-bytes:${cap === null ? "off" : cap}`;
|
|
39
|
+
}
|
|
9
40
|
function withResponseSizeLimit(maxResponseBytes, fn) {
|
|
10
|
-
if (
|
|
41
|
+
if (maxResponseBytes === void 0 && responseSizeLimitStorage.getStore()) {
|
|
11
42
|
return fn();
|
|
12
43
|
}
|
|
13
|
-
|
|
44
|
+
const slot = newSlot(maxResponseBytes);
|
|
45
|
+
return responseSizeLimitStorage.run(slot, () => rethrowRecordedViolation(slot, fn));
|
|
46
|
+
}
|
|
47
|
+
async function rethrowRecordedViolation(slot, fn) {
|
|
48
|
+
try {
|
|
49
|
+
return await fn();
|
|
50
|
+
} catch (error) {
|
|
51
|
+
const violation = slot.violation;
|
|
52
|
+
if (!violation || error instanceof ResponseTooLargeError) throw error;
|
|
53
|
+
const surfaced = new ResponseTooLargeError(
|
|
54
|
+
violation.limit,
|
|
55
|
+
violation.bytesRead,
|
|
56
|
+
violation.url,
|
|
57
|
+
violation.contentLengthHeader
|
|
58
|
+
);
|
|
59
|
+
Object.defineProperty(surfaced, "cause", { value: error, configurable: true });
|
|
60
|
+
throw surfaced;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function recordViolation(slot, error) {
|
|
64
|
+
if (slot && !slot.violation) slot.violation = error;
|
|
65
|
+
return error;
|
|
14
66
|
}
|
|
15
67
|
function urlOfInput(input) {
|
|
16
68
|
if (typeof input === "string") return input;
|
|
17
69
|
if (input instanceof URL) return input.toString();
|
|
18
70
|
return input.url;
|
|
19
71
|
}
|
|
20
|
-
function redactUrlForError(url) {
|
|
21
|
-
try {
|
|
22
|
-
const parsed = new URL(url);
|
|
23
|
-
parsed.search = "";
|
|
24
|
-
return parsed.toString();
|
|
25
|
-
} catch {
|
|
26
|
-
return url;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
function withIdentityEncoding(init) {
|
|
30
|
-
const headers = new Headers(init?.headers);
|
|
31
|
-
if (!headers.has("accept-encoding")) {
|
|
32
|
-
headers.set("accept-encoding", "identity");
|
|
33
|
-
}
|
|
34
|
-
return { ...init ?? {}, headers };
|
|
35
|
-
}
|
|
36
72
|
function wrapFetchWithSizeLimit(upstream) {
|
|
37
73
|
const wrapped = async (input, init) => {
|
|
38
74
|
const slot = responseSizeLimitStorage.getStore();
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
75
|
+
const maxBytes = slot ? slot.maxResponseBytes : DEFAULT_MAX_RESPONSE_BYTES;
|
|
76
|
+
if (maxBytes === null) return upstream(input, init);
|
|
77
|
+
const response = await upstream(input, init);
|
|
78
|
+
if (NULL_BODY_STATUSES.has(response.status)) return response;
|
|
79
|
+
const skipDeclaredLength = methodOf(input, init) === "HEAD";
|
|
80
|
+
const url = sanitizeTransportUrl(urlOfInput(input));
|
|
81
|
+
if (isEventStream(response)) {
|
|
82
|
+
const connectionScoped = methodOf(input, init) === "GET";
|
|
83
|
+
const { limit, meter } = streamBudgetFor(connectionScoped, slot, maxBytes);
|
|
84
|
+
return enforceEventStreamLimit(
|
|
85
|
+
response,
|
|
86
|
+
maxBytes,
|
|
87
|
+
limit,
|
|
88
|
+
meter,
|
|
89
|
+
url,
|
|
90
|
+
connectionScoped ? void 0 : slot,
|
|
91
|
+
skipDeclaredLength
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
return enforceSizeLimit(response, maxBytes, url, slot, skipDeclaredLength);
|
|
42
95
|
};
|
|
43
96
|
return wrapped;
|
|
44
97
|
}
|
|
45
|
-
function
|
|
46
|
-
if (
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
98
|
+
function streamBudgetFor(connectionScoped, slot, maxBytes) {
|
|
99
|
+
if (connectionScoped) return { limit: sseBudgetFor(maxBytes), meter: { consumed: 0 } };
|
|
100
|
+
return {
|
|
101
|
+
limit: slot?.streamLimit ?? sseBudgetFor(maxBytes),
|
|
102
|
+
meter: slot?.streamMeter ?? { consumed: 0 }
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function methodOf(input, init) {
|
|
106
|
+
const method = init?.method ?? (typeof Request !== "undefined" && input instanceof Request ? input.method : "GET");
|
|
107
|
+
return method.toUpperCase();
|
|
108
|
+
}
|
|
109
|
+
const NULL_BODY_STATUSES = /* @__PURE__ */ new Set([101, 103, 204, 205, 304]);
|
|
110
|
+
function isEventStream(response) {
|
|
111
|
+
return response.headers.get("content-type")?.toLowerCase().startsWith("text/event-stream") === true;
|
|
112
|
+
}
|
|
113
|
+
function enforceSizeLimit(response, maxBytes, url, slot, skipDeclaredLength = false) {
|
|
114
|
+
const declared = skipDeclaredLength ? void 0 : parseContentLength(response.headers.get("content-length"));
|
|
50
115
|
if (declared !== void 0 && declared > maxBytes) {
|
|
51
|
-
response
|
|
52
|
-
|
|
53
|
-
throw new ResponseTooLargeError(maxBytes, 0, url, declared);
|
|
116
|
+
cancelBody(response);
|
|
117
|
+
throw recordViolation(slot, new ResponseTooLargeError(maxBytes, 0, url, declared));
|
|
54
118
|
}
|
|
55
119
|
if (!response.body) return response;
|
|
56
120
|
let bytesRead = 0;
|
|
@@ -58,13 +122,107 @@ function enforceSizeLimit(response, maxBytes, url) {
|
|
|
58
122
|
transform(chunk, controller) {
|
|
59
123
|
bytesRead += chunk.byteLength;
|
|
60
124
|
if (bytesRead > maxBytes) {
|
|
61
|
-
controller.error(new ResponseTooLargeError(maxBytes, bytesRead, url));
|
|
125
|
+
controller.error(recordViolation(slot, new ResponseTooLargeError(maxBytes, bytesRead, url)));
|
|
62
126
|
return;
|
|
63
127
|
}
|
|
64
128
|
controller.enqueue(chunk);
|
|
65
129
|
}
|
|
66
130
|
});
|
|
67
|
-
return
|
|
131
|
+
return respondWith(response, response.body.pipeThrough(counter));
|
|
132
|
+
}
|
|
133
|
+
const CR = 13;
|
|
134
|
+
const LF = 10;
|
|
135
|
+
function enforceEventStreamLimit(response, maxBytes, streamLimit, meter, url, slot, skipDeclaredLength = false) {
|
|
136
|
+
const remaining = streamLimit - meter.consumed;
|
|
137
|
+
const declared = skipDeclaredLength ? void 0 : parseContentLength(response.headers.get("content-length"));
|
|
138
|
+
if (declared !== void 0 && declared > remaining) {
|
|
139
|
+
cancelBody(response);
|
|
140
|
+
throw recordViolation(slot, new ResponseTooLargeError(streamLimit, meter.consumed, url, declared));
|
|
141
|
+
}
|
|
142
|
+
if (!response.body) return response;
|
|
143
|
+
let bytesInEvent = 0;
|
|
144
|
+
let lineEndings = 0;
|
|
145
|
+
let pendingCR = false;
|
|
146
|
+
let separatorTail = false;
|
|
147
|
+
let pendingReset = false;
|
|
148
|
+
const counter = new TransformStream({
|
|
149
|
+
transform(chunk, controller) {
|
|
150
|
+
meter.consumed += chunk.byteLength;
|
|
151
|
+
if (meter.consumed > streamLimit) {
|
|
152
|
+
controller.error(recordViolation(slot, new ResponseTooLargeError(streamLimit, meter.consumed, url)));
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
if (chunk.length === 0) {
|
|
156
|
+
controller.enqueue(chunk);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
if (chunk.indexOf(LF) === -1 && chunk.indexOf(CR) === -1) {
|
|
160
|
+
if (pendingReset) {
|
|
161
|
+
pendingReset = false;
|
|
162
|
+
separatorTail = false;
|
|
163
|
+
bytesInEvent = 0;
|
|
164
|
+
}
|
|
165
|
+
bytesInEvent += chunk.length;
|
|
166
|
+
lineEndings = 0;
|
|
167
|
+
pendingCR = false;
|
|
168
|
+
if (bytesInEvent > maxBytes) {
|
|
169
|
+
controller.error(recordViolation(slot, new ResponseTooLargeError(maxBytes, bytesInEvent, url)));
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
controller.enqueue(chunk);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
for (let i = 0; i < chunk.length; i += 1) {
|
|
176
|
+
const byte = chunk[i];
|
|
177
|
+
if (pendingReset) {
|
|
178
|
+
pendingReset = false;
|
|
179
|
+
if (separatorTail && byte === LF) {
|
|
180
|
+
separatorTail = false;
|
|
181
|
+
pendingCR = false;
|
|
182
|
+
bytesInEvent += 1;
|
|
183
|
+
if (bytesInEvent > maxBytes) {
|
|
184
|
+
controller.error(recordViolation(slot, new ResponseTooLargeError(maxBytes, bytesInEvent, url)));
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
bytesInEvent = 0;
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
separatorTail = false;
|
|
191
|
+
bytesInEvent = 0;
|
|
192
|
+
}
|
|
193
|
+
bytesInEvent += 1;
|
|
194
|
+
if (byte === CR) {
|
|
195
|
+
lineEndings += 1;
|
|
196
|
+
pendingCR = true;
|
|
197
|
+
} else if (byte === LF) {
|
|
198
|
+
if (!pendingCR) lineEndings += 1;
|
|
199
|
+
pendingCR = false;
|
|
200
|
+
} else {
|
|
201
|
+
lineEndings = 0;
|
|
202
|
+
pendingCR = false;
|
|
203
|
+
}
|
|
204
|
+
if (bytesInEvent > maxBytes) {
|
|
205
|
+
controller.error(recordViolation(slot, new ResponseTooLargeError(maxBytes, bytesInEvent, url)));
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
if (lineEndings >= 2) {
|
|
209
|
+
lineEndings = 0;
|
|
210
|
+
pendingReset = true;
|
|
211
|
+
separatorTail = pendingCR;
|
|
212
|
+
pendingCR = false;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
controller.enqueue(chunk);
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
return respondWith(response, response.body.pipeThrough(counter));
|
|
219
|
+
}
|
|
220
|
+
function cancelBody(response) {
|
|
221
|
+
response.body?.cancel().catch(() => {
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
function respondWith(response, body) {
|
|
225
|
+
return new Response(body, {
|
|
68
226
|
status: response.status,
|
|
69
227
|
statusText: response.statusText,
|
|
70
228
|
headers: response.headers
|
|
@@ -78,6 +236,9 @@ function parseContentLength(value) {
|
|
|
78
236
|
return Number.isFinite(parsed) ? parsed : void 0;
|
|
79
237
|
}
|
|
80
238
|
export {
|
|
239
|
+
DEFAULT_MAX_RESPONSE_BYTES,
|
|
240
|
+
SSE_CUMULATIVE_BUDGET_MULTIPLIER,
|
|
241
|
+
responseSizeCapCacheKey,
|
|
81
242
|
responseSizeLimitStorage,
|
|
82
243
|
withResponseSizeLimit,
|
|
83
244
|
wrapFetchWithSizeLimit
|
|
@@ -23,6 +23,7 @@ __export(consumer_runtime_exports, {
|
|
|
23
23
|
});
|
|
24
24
|
module.exports = __toCommonJS(consumer_runtime_exports);
|
|
25
25
|
var import_jcs = require('../utils/jcs.js');
|
|
26
|
+
var import_pagination = require('./pagination.js');
|
|
26
27
|
var import_reconciliation = require('./reconciliation.js');
|
|
27
28
|
const DEFAULT_POLL_INTERVAL_MS = 6e4;
|
|
28
29
|
const DEFAULT_LEASE_MS = 3e4;
|
|
@@ -59,7 +60,7 @@ async function drainReportingChanges(options, stopAfterChangeDetected) {
|
|
|
59
60
|
...options.request,
|
|
60
61
|
view: "periods",
|
|
61
62
|
changes_after: options.changesAfter,
|
|
62
|
-
...cursor ? {
|
|
63
|
+
pagination: { max_results: (0, import_pagination.reportingMaxPageSize)(), ...cursor ? { cursor } : {} }
|
|
63
64
|
},
|
|
64
65
|
{ signal }
|
|
65
66
|
),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { canonicalJsonSha256 } from "../utils/jcs.mjs";
|
|
2
|
+
import { reportingMaxPageSize } from "./pagination.mjs";
|
|
2
3
|
import {
|
|
3
4
|
ReportingReconciliationError,
|
|
4
5
|
reconcileReporting
|
|
@@ -38,7 +39,7 @@ async function drainReportingChanges(options, stopAfterChangeDetected) {
|
|
|
38
39
|
...options.request,
|
|
39
40
|
view: "periods",
|
|
40
41
|
changes_after: options.changesAfter,
|
|
41
|
-
...cursor ? {
|
|
42
|
+
pagination: { max_results: reportingMaxPageSize(), ...cursor ? { cursor } : {} }
|
|
42
43
|
},
|
|
43
44
|
{ signal }
|
|
44
45
|
),
|
|
@@ -31,12 +31,13 @@ module.exports = __toCommonJS(handler_exports);
|
|
|
31
31
|
var import_node_crypto = require("node:crypto");
|
|
32
32
|
var import_version = require('../../version.js');
|
|
33
33
|
var import_async_outcome = require('../../server/decisioning/async-outcome.js');
|
|
34
|
+
var import_schema_loader = require('../../validation/schema-loader.js');
|
|
34
35
|
var import_source = require('../source/index.js');
|
|
35
36
|
var import_coverage = require('./coverage.js');
|
|
36
37
|
var import_health = require('./health.js');
|
|
37
38
|
var import_instant = require('./instant.js');
|
|
38
39
|
var import_revision_metadata = require('./revision-metadata.js');
|
|
39
|
-
var
|
|
40
|
+
var import_row_storage_errors = require('./row-storage-errors.js');
|
|
40
41
|
var import_schedule = require('./schedule.js');
|
|
41
42
|
var import_types = require('./types.js');
|
|
42
43
|
function createReportingStatusHandler(store, options) {
|
|
@@ -48,6 +49,7 @@ function createReportingStatusHandler(store, options) {
|
|
|
48
49
|
)
|
|
49
50
|
);
|
|
50
51
|
const activeReadsByAccount = /* @__PURE__ */ new Map();
|
|
52
|
+
reportingPageBounds();
|
|
51
53
|
return async (request, context) => {
|
|
52
54
|
const raw = request;
|
|
53
55
|
const resolvedAccount = isRecord(context.account) ? context.account : {};
|
|
@@ -81,9 +83,7 @@ function createReportingStatusHandler(store, options) {
|
|
|
81
83
|
...typeof raw.changes_after === "string" ? { changes_after: raw.changes_after } : {},
|
|
82
84
|
...isRecord(raw.period) ? { period: raw.period } : {}
|
|
83
85
|
};
|
|
84
|
-
const pagination =
|
|
85
|
-
const limitValue = pagination.max_results ?? pagination.limit ?? 100;
|
|
86
|
-
const limit = typeof limitValue === "number" && Number.isFinite(limitValue) ? Math.max(1, Math.min(500, Math.trunc(limitValue))) : 100;
|
|
86
|
+
const { pageSize: limit, pagination } = reportingPagination(raw.pagination);
|
|
87
87
|
const cursor = typeof pagination.cursor === "string" ? pagination.cursor : void 0;
|
|
88
88
|
let snapshotId;
|
|
89
89
|
if (cursor) {
|
|
@@ -99,7 +99,7 @@ function createReportingStatusHandler(store, options) {
|
|
|
99
99
|
try {
|
|
100
100
|
snapshot = await store.createSnapshot(query);
|
|
101
101
|
} catch (error) {
|
|
102
|
-
if (
|
|
102
|
+
if ((0, import_types.isReportingLedgerErrorNamed)(error, "ReportingLedgerSnapshotUnavailableError") || error instanceof ReportingReadCapacityError) {
|
|
103
103
|
return lookupUnavailable(view);
|
|
104
104
|
}
|
|
105
105
|
if (isContinuityError(error)) return operationalUnavailable(view);
|
|
@@ -111,7 +111,7 @@ function createReportingStatusHandler(store, options) {
|
|
|
111
111
|
try {
|
|
112
112
|
page = await store.readSnapshotPage(snapshotId ?? snapshot.snapshotId, accountId, cursor, limit);
|
|
113
113
|
} catch (error) {
|
|
114
|
-
if (
|
|
114
|
+
if ((0, import_types.isReportingLedgerErrorNamed)(error, "ReportingLedgerSnapshotUnavailableError") || error instanceof ReportingReadCapacityError) {
|
|
115
115
|
return lookupUnavailable(view);
|
|
116
116
|
}
|
|
117
117
|
if (isContinuityError(error)) return operationalUnavailable(view);
|
|
@@ -275,7 +275,7 @@ function createReportingStatusHandler(store, options) {
|
|
|
275
275
|
else revisionRows = page2.rows;
|
|
276
276
|
}
|
|
277
277
|
} catch (error) {
|
|
278
|
-
if (error instanceof ReportingReadCapacityError || (0,
|
|
278
|
+
if (error instanceof ReportingReadCapacityError || (0, import_row_storage_errors.isReportingRowStoreError)(error)) {
|
|
279
279
|
return lookupUnavailable(view);
|
|
280
280
|
}
|
|
281
281
|
throw error;
|
|
@@ -412,7 +412,7 @@ function createReportingStatusHandler(store, options) {
|
|
|
412
412
|
issues: issues.map(wireIssue)
|
|
413
413
|
};
|
|
414
414
|
} catch (error) {
|
|
415
|
-
if (error
|
|
415
|
+
if ((0, import_types.isReportingLedgerErrorNamed)(error, "ReportingLedgerIssueIntegrityError")) return operationalUnavailable(view);
|
|
416
416
|
throw error;
|
|
417
417
|
} finally {
|
|
418
418
|
releaseReadSlot();
|
|
@@ -420,6 +420,45 @@ function createReportingStatusHandler(store, options) {
|
|
|
420
420
|
};
|
|
421
421
|
}
|
|
422
422
|
const REPORTING_STATUS_REVISION_VIEW_MAX_ROWS = 1e4;
|
|
423
|
+
let pageBounds;
|
|
424
|
+
function reportingPageBounds() {
|
|
425
|
+
if (pageBounds) return pageBounds;
|
|
426
|
+
const document = (0, import_schema_loader.getSchemaDocumentByRef)("core/pagination-request.json");
|
|
427
|
+
const field = document?.schema.properties?.max_results;
|
|
428
|
+
const { minimum, maximum, default: initial } = field ?? {};
|
|
429
|
+
if (!Number.isSafeInteger(minimum) || !Number.isSafeInteger(maximum) || !Number.isSafeInteger(initial) || minimum < 1 || maximum < minimum || initial < minimum || initial > maximum) {
|
|
430
|
+
throw new Error("The AdCP pagination-request schema does not define bounds for max_results");
|
|
431
|
+
}
|
|
432
|
+
pageBounds = Object.freeze({
|
|
433
|
+
minimum,
|
|
434
|
+
maximum,
|
|
435
|
+
default: initial
|
|
436
|
+
});
|
|
437
|
+
return pageBounds;
|
|
438
|
+
}
|
|
439
|
+
function reportingPagination(value) {
|
|
440
|
+
const bounds = reportingPageBounds();
|
|
441
|
+
if (value !== void 0 && !isRecord(value)) {
|
|
442
|
+
throw new import_async_outcome.AdcpError("VALIDATION_ERROR", { message: "pagination must be an object", field: "pagination" });
|
|
443
|
+
}
|
|
444
|
+
const pagination = value ?? {};
|
|
445
|
+
if (pagination.cursor !== void 0 && typeof pagination.cursor !== "string") {
|
|
446
|
+
throw new import_async_outcome.AdcpError("VALIDATION_ERROR", {
|
|
447
|
+
message: "pagination.cursor must be a string",
|
|
448
|
+
field: "pagination.cursor"
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
const size = pagination.max_results;
|
|
452
|
+
if (size === void 0) return { pageSize: bounds.default, pagination };
|
|
453
|
+
if (typeof size !== "number" || !Number.isInteger(size) || size < bounds.minimum || size > bounds.maximum) {
|
|
454
|
+
throw new import_async_outcome.AdcpError("VALIDATION_ERROR", {
|
|
455
|
+
message: `pagination.max_results must be an integer from ${bounds.minimum} to ${bounds.maximum}`,
|
|
456
|
+
field: "pagination.max_results",
|
|
457
|
+
suggestion: `Send an integer from ${bounds.minimum} to ${bounds.maximum}, or omit it for the default of ${bounds.default}.`
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
return { pageSize: size, pagination };
|
|
461
|
+
}
|
|
423
462
|
function reportingRevisionNotFound() {
|
|
424
463
|
return new import_async_outcome.AdcpError("REFERENCE_NOT_FOUND", {
|
|
425
464
|
message: "Reporting revision is unavailable",
|
|
@@ -432,6 +471,7 @@ function createReportingDeliveryHandler(store, options = {}) {
|
|
|
432
471
|
if (legacyRevisionReader !== void 0 && typeof legacyRevisionReader !== "function") {
|
|
433
472
|
throw new TypeError("legacyRevisionReader must be a function");
|
|
434
473
|
}
|
|
474
|
+
reportingPageBounds();
|
|
435
475
|
const activeReadsByAccount = /* @__PURE__ */ new Map();
|
|
436
476
|
const readFromSdkLedger = async (request, context) => {
|
|
437
477
|
const accountId = resolvedAccountId(context.account);
|
|
@@ -454,12 +494,11 @@ function createReportingDeliveryHandler(store, options = {}) {
|
|
|
454
494
|
field: "reporting_revision_id"
|
|
455
495
|
});
|
|
456
496
|
}
|
|
497
|
+
const { pageSize: maxResults, pagination } = reportingPagination(raw.pagination);
|
|
457
498
|
const revision = await (0, import_revision_metadata.getRevisionMetadataFromStore)(store, raw.reporting_revision_id, accountId);
|
|
458
499
|
if (!revision) return SDK_REVISION_NOT_OWNED;
|
|
459
500
|
const obligation = await store.getObligation(revision.reporting_obligation_id);
|
|
460
501
|
if (!obligation || obligation.account.account_id !== accountId) return SDK_REVISION_NOT_OWNED;
|
|
461
|
-
const pagination = isRecord(raw.pagination) ? raw.pagination : {};
|
|
462
|
-
const maxResults = typeof pagination.max_results === "number" && Number.isFinite(pagination.max_results) ? Math.max(1, Math.min(500, Math.trunc(pagination.max_results))) : 100;
|
|
463
502
|
const totalCount = revision.binding.rowCount;
|
|
464
503
|
let offset = 0;
|
|
465
504
|
if (typeof pagination.cursor === "string") {
|
|
@@ -485,7 +524,7 @@ function createReportingDeliveryHandler(store, options = {}) {
|
|
|
485
524
|
...context.signal ? { signal: context.signal } : {}
|
|
486
525
|
});
|
|
487
526
|
} catch (error) {
|
|
488
|
-
if ((0,
|
|
527
|
+
if ((0, import_row_storage_errors.isReportingRowStoreError)(error)) {
|
|
489
528
|
if (error.code === "ROWS_EXPIRED") throw reportingRevisionNotFound();
|
|
490
529
|
throw new import_async_outcome.AdcpError("SERVICE_UNAVAILABLE", {
|
|
491
530
|
message: "Reporting revision rows are temporarily unavailable"
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { ADCP_MAJOR_VERSION, ADCP_VERSION, toReleasePrecisionVersion } from "../../version.mjs";
|
|
3
3
|
import { AdcpError } from "../../server/decisioning/async-outcome.mjs";
|
|
4
|
+
import { getSchemaDocumentByRef } from "../../validation/schema-loader.mjs";
|
|
4
5
|
import { canonicalJsonV1 } from "../source/index.mjs";
|
|
5
6
|
import {
|
|
6
7
|
evaluateReportingLedgerCoverageV1,
|
|
@@ -16,14 +17,13 @@ import {
|
|
|
16
17
|
reportingEffectiveConsumerMismatchEscalationV1,
|
|
17
18
|
projectReportingConsumerStatusMismatchV1,
|
|
18
19
|
projectReportingObligationHealthV1,
|
|
19
|
-
projectReportingUnreadableRevisionHealthV1
|
|
20
|
-
ReportingLedgerIssueIntegrityError
|
|
20
|
+
projectReportingUnreadableRevisionHealthV1
|
|
21
21
|
} from "./health.mjs";
|
|
22
22
|
import { compareReportingInstants } from "./instant.mjs";
|
|
23
23
|
import { getRevisionMetadataFromStore, readRevisionRowsFromStore } from "./revision-metadata.mjs";
|
|
24
|
-
import { isReportingRowStoreError } from "./row-storage.mjs";
|
|
24
|
+
import { isReportingRowStoreError } from "./row-storage-errors.mjs";
|
|
25
25
|
import { reportingPeriodSchedule } from "./schedule.mjs";
|
|
26
|
-
import {
|
|
26
|
+
import { isReportingLedgerErrorNamed } from "./types.mjs";
|
|
27
27
|
function createReportingStatusHandler(store, options) {
|
|
28
28
|
const consumerMismatchEscalation = assertReportingConsumerMismatchEscalation(
|
|
29
29
|
reportingEffectiveConsumerMismatchEscalationV1(
|
|
@@ -33,6 +33,7 @@ function createReportingStatusHandler(store, options) {
|
|
|
33
33
|
)
|
|
34
34
|
);
|
|
35
35
|
const activeReadsByAccount = /* @__PURE__ */ new Map();
|
|
36
|
+
reportingPageBounds();
|
|
36
37
|
return async (request, context) => {
|
|
37
38
|
const raw = request;
|
|
38
39
|
const resolvedAccount = isRecord(context.account) ? context.account : {};
|
|
@@ -66,9 +67,7 @@ function createReportingStatusHandler(store, options) {
|
|
|
66
67
|
...typeof raw.changes_after === "string" ? { changes_after: raw.changes_after } : {},
|
|
67
68
|
...isRecord(raw.period) ? { period: raw.period } : {}
|
|
68
69
|
};
|
|
69
|
-
const pagination =
|
|
70
|
-
const limitValue = pagination.max_results ?? pagination.limit ?? 100;
|
|
71
|
-
const limit = typeof limitValue === "number" && Number.isFinite(limitValue) ? Math.max(1, Math.min(500, Math.trunc(limitValue))) : 100;
|
|
70
|
+
const { pageSize: limit, pagination } = reportingPagination(raw.pagination);
|
|
72
71
|
const cursor = typeof pagination.cursor === "string" ? pagination.cursor : void 0;
|
|
73
72
|
let snapshotId;
|
|
74
73
|
if (cursor) {
|
|
@@ -84,7 +83,7 @@ function createReportingStatusHandler(store, options) {
|
|
|
84
83
|
try {
|
|
85
84
|
snapshot = await store.createSnapshot(query);
|
|
86
85
|
} catch (error) {
|
|
87
|
-
if (error
|
|
86
|
+
if (isReportingLedgerErrorNamed(error, "ReportingLedgerSnapshotUnavailableError") || error instanceof ReportingReadCapacityError) {
|
|
88
87
|
return lookupUnavailable(view);
|
|
89
88
|
}
|
|
90
89
|
if (isContinuityError(error)) return operationalUnavailable(view);
|
|
@@ -96,7 +95,7 @@ function createReportingStatusHandler(store, options) {
|
|
|
96
95
|
try {
|
|
97
96
|
page = await store.readSnapshotPage(snapshotId ?? snapshot.snapshotId, accountId, cursor, limit);
|
|
98
97
|
} catch (error) {
|
|
99
|
-
if (error
|
|
98
|
+
if (isReportingLedgerErrorNamed(error, "ReportingLedgerSnapshotUnavailableError") || error instanceof ReportingReadCapacityError) {
|
|
100
99
|
return lookupUnavailable(view);
|
|
101
100
|
}
|
|
102
101
|
if (isContinuityError(error)) return operationalUnavailable(view);
|
|
@@ -397,7 +396,7 @@ function createReportingStatusHandler(store, options) {
|
|
|
397
396
|
issues: issues.map(wireIssue)
|
|
398
397
|
};
|
|
399
398
|
} catch (error) {
|
|
400
|
-
if (error
|
|
399
|
+
if (isReportingLedgerErrorNamed(error, "ReportingLedgerIssueIntegrityError")) return operationalUnavailable(view);
|
|
401
400
|
throw error;
|
|
402
401
|
} finally {
|
|
403
402
|
releaseReadSlot();
|
|
@@ -405,6 +404,45 @@ function createReportingStatusHandler(store, options) {
|
|
|
405
404
|
};
|
|
406
405
|
}
|
|
407
406
|
const REPORTING_STATUS_REVISION_VIEW_MAX_ROWS = 1e4;
|
|
407
|
+
let pageBounds;
|
|
408
|
+
function reportingPageBounds() {
|
|
409
|
+
if (pageBounds) return pageBounds;
|
|
410
|
+
const document = getSchemaDocumentByRef("core/pagination-request.json");
|
|
411
|
+
const field = document?.schema.properties?.max_results;
|
|
412
|
+
const { minimum, maximum, default: initial } = field ?? {};
|
|
413
|
+
if (!Number.isSafeInteger(minimum) || !Number.isSafeInteger(maximum) || !Number.isSafeInteger(initial) || minimum < 1 || maximum < minimum || initial < minimum || initial > maximum) {
|
|
414
|
+
throw new Error("The AdCP pagination-request schema does not define bounds for max_results");
|
|
415
|
+
}
|
|
416
|
+
pageBounds = Object.freeze({
|
|
417
|
+
minimum,
|
|
418
|
+
maximum,
|
|
419
|
+
default: initial
|
|
420
|
+
});
|
|
421
|
+
return pageBounds;
|
|
422
|
+
}
|
|
423
|
+
function reportingPagination(value) {
|
|
424
|
+
const bounds = reportingPageBounds();
|
|
425
|
+
if (value !== void 0 && !isRecord(value)) {
|
|
426
|
+
throw new AdcpError("VALIDATION_ERROR", { message: "pagination must be an object", field: "pagination" });
|
|
427
|
+
}
|
|
428
|
+
const pagination = value ?? {};
|
|
429
|
+
if (pagination.cursor !== void 0 && typeof pagination.cursor !== "string") {
|
|
430
|
+
throw new AdcpError("VALIDATION_ERROR", {
|
|
431
|
+
message: "pagination.cursor must be a string",
|
|
432
|
+
field: "pagination.cursor"
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
const size = pagination.max_results;
|
|
436
|
+
if (size === void 0) return { pageSize: bounds.default, pagination };
|
|
437
|
+
if (typeof size !== "number" || !Number.isInteger(size) || size < bounds.minimum || size > bounds.maximum) {
|
|
438
|
+
throw new AdcpError("VALIDATION_ERROR", {
|
|
439
|
+
message: `pagination.max_results must be an integer from ${bounds.minimum} to ${bounds.maximum}`,
|
|
440
|
+
field: "pagination.max_results",
|
|
441
|
+
suggestion: `Send an integer from ${bounds.minimum} to ${bounds.maximum}, or omit it for the default of ${bounds.default}.`
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
return { pageSize: size, pagination };
|
|
445
|
+
}
|
|
408
446
|
function reportingRevisionNotFound() {
|
|
409
447
|
return new AdcpError("REFERENCE_NOT_FOUND", {
|
|
410
448
|
message: "Reporting revision is unavailable",
|
|
@@ -417,6 +455,7 @@ function createReportingDeliveryHandler(store, options = {}) {
|
|
|
417
455
|
if (legacyRevisionReader !== void 0 && typeof legacyRevisionReader !== "function") {
|
|
418
456
|
throw new TypeError("legacyRevisionReader must be a function");
|
|
419
457
|
}
|
|
458
|
+
reportingPageBounds();
|
|
420
459
|
const activeReadsByAccount = /* @__PURE__ */ new Map();
|
|
421
460
|
const readFromSdkLedger = async (request, context) => {
|
|
422
461
|
const accountId = resolvedAccountId(context.account);
|
|
@@ -439,12 +478,11 @@ function createReportingDeliveryHandler(store, options = {}) {
|
|
|
439
478
|
field: "reporting_revision_id"
|
|
440
479
|
});
|
|
441
480
|
}
|
|
481
|
+
const { pageSize: maxResults, pagination } = reportingPagination(raw.pagination);
|
|
442
482
|
const revision = await getRevisionMetadataFromStore(store, raw.reporting_revision_id, accountId);
|
|
443
483
|
if (!revision) return SDK_REVISION_NOT_OWNED;
|
|
444
484
|
const obligation = await store.getObligation(revision.reporting_obligation_id);
|
|
445
485
|
if (!obligation || obligation.account.account_id !== accountId) return SDK_REVISION_NOT_OWNED;
|
|
446
|
-
const pagination = isRecord(raw.pagination) ? raw.pagination : {};
|
|
447
|
-
const maxResults = typeof pagination.max_results === "number" && Number.isFinite(pagination.max_results) ? Math.max(1, Math.min(500, Math.trunc(pagination.max_results))) : 100;
|
|
448
486
|
const totalCount = revision.binding.rowCount;
|
|
449
487
|
let offset = 0;
|
|
450
488
|
if (typeof pagination.cursor === "string") {
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Reliable Reporting ledger
|
|
2
|
+
* Reliable Reporting protocol layer: the ledger store interface, the protocol handlers, the producer,
|
|
3
|
+
* status ingest, row encoding and the health, coverage and lifecycle helpers.
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* Storage implementations (PostgreSQL ledger store, row storage, managed delivery, notification activity,
|
|
6
|
+
* the cloud providers and the BigQuery sink) live in `@adcp/reporting-storage`, which depends on this
|
|
7
|
+
* package. Nothing here imports it. A store from any package works with these handlers as long as it
|
|
8
|
+
* implements `ReportingLedgerStore`.
|
|
9
|
+
*
|
|
10
|
+
* The store, transaction, lease and row-read interfaces in `./types` are tagged `@experimental`: they
|
|
11
|
+
* change together with `@adcp/reporting-storage`, which is pre-1.0. The protocol-facing handlers,
|
|
12
|
+
* producer, status ingest, health, coverage and lifecycle helpers follow normal semver.
|
|
7
13
|
*
|
|
8
14
|
* Stability policy: https://github.com/adcontextprotocol/adcp-client/blob/main/docs/guides/REPORTING-STABILITY.md
|
|
9
15
|
*
|
|
@@ -13,18 +19,15 @@ export * from './types.mjs';
|
|
|
13
19
|
export * from './health.mjs';
|
|
14
20
|
export * from './coverage.mjs';
|
|
15
21
|
export * from './lifecycle.mjs';
|
|
16
|
-
export * from './postgres.mjs';
|
|
17
22
|
export * from './producer.mjs';
|
|
18
23
|
export * from './handler.mjs';
|
|
19
24
|
export * from './status-ingest.mjs';
|
|
20
25
|
export * from './consumer-status-identity.mjs';
|
|
21
|
-
export * from './managed.mjs';
|
|
22
|
-
export * from './managed-router.mjs';
|
|
23
|
-
export * from './managed-postgres.mjs';
|
|
24
|
-
export * from './object-writes.mjs';
|
|
25
|
-
export * from './notification-activity.mjs';
|
|
26
26
|
export * from './row-encoding.mjs';
|
|
27
|
-
export * from './row-storage-
|
|
28
|
-
export * from './
|
|
29
|
-
export * from './
|
|
30
|
-
export
|
|
27
|
+
export * from './row-storage-errors.mjs';
|
|
28
|
+
export * from './receipts.mjs';
|
|
29
|
+
export * from './offering-validation.mjs';
|
|
30
|
+
export { compareReportingInstants } from './instant.mjs';
|
|
31
|
+
export { isFrozenCalendarRulesMismatch, reportingPeriodDate, reportingPeriodSchedule } from './schedule.mjs';
|
|
32
|
+
export { isReportingAdjustmentReceiptEvidence, isReportingReceiptEvidence, isReportingVerificationEvidence, } from '../evidence.mjs';
|
|
33
|
+
export { isWellFormedUnicodeString } from '../../utils/well-formed-unicode.mjs';
|