@adcp/sdk 16.0.0-beta.3 → 16.0.0-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/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/index.d.mts +1 -1
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/index.js +2 -0
- package/dist/lib/index.mjs +7 -1
- 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/signer.js +9 -6
- package/dist/lib/signing/signer.mjs +10 -7
- package/dist/lib/signing/web-bot-auth.js +103 -37
- package/dist/lib/signing/web-bot-auth.mjs +108 -37
- 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 +10 -9
- package/dist/lib/testing/storyboard/request-signing/builder.mjs +10 -9
- package/dist/lib/testing/storyboard/runner.js +94 -25
- package/dist/lib/testing/storyboard/runner.mjs +94 -25
- 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/schemas.generated.d.ts +907 -60
- package/dist/lib/types/schemas.generated.js +7 -7
- package/dist/lib/types/schemas.generated.mjs +7 -7
- 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 +23 -5
- 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/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 +13 -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
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scheduler primitives shared by `createReliableReportingService` and by services composed with it
|
|
3
|
+
* (for example `@adcp/reporting-storage/service`). They are exported so a composition can pace its own
|
|
4
|
+
* background passes and report failures the same way the Core scheduler does.
|
|
5
|
+
*/
|
|
6
|
+
import type { ReportingLedgerStore } from '../ledger/types.mjs';
|
|
7
|
+
/**
|
|
8
|
+
* The error's own message only, credential-redacted, bounded, and total.
|
|
9
|
+
*
|
|
10
|
+
* Stacks and error objects can carry request payloads and upstream credentials
|
|
11
|
+
* into a log sink the adopter did not choose, so only `message` is read. Every
|
|
12
|
+
* step is guarded because the value is arbitrary: `String(Object.create(null))`
|
|
13
|
+
* throws, a `Symbol.toPrimitive` or `message` getter can throw or run adopter
|
|
14
|
+
* code, and a Proxy can trap the prototype walk `instanceof` performs. This
|
|
15
|
+
* function runs while building the diagnostic, outside the catch that guards
|
|
16
|
+
* the logger call, so a throw here escaped `reportSchedulerError`, rejected the
|
|
17
|
+
* scheduler loop, and surfaced as an unhandled rejection — killing the
|
|
18
|
+
* background loop, or the host, over an error object's shape.
|
|
19
|
+
*/
|
|
20
|
+
export declare function reportingSchedulerErrorMessage(error: unknown): string;
|
|
21
|
+
export declare function reportingSchedulerDelay(milliseconds: number, signal: AbortSignal): Promise<void>;
|
|
22
|
+
/** Start each pass one tenant further along so no fixed order can starve. */
|
|
23
|
+
export declare function rotateReportingRoster<T>(values: readonly T[], by: number): T[];
|
|
24
|
+
/**
|
|
25
|
+
* Every account the ledger currently holds a configuration for. This is the
|
|
26
|
+
* roster a deployment-wide worker is authorized over, so it is also the roster
|
|
27
|
+
* the per-account budgets apply to.
|
|
28
|
+
*/
|
|
29
|
+
export declare function reportingDeploymentWideAccountIds(store: ReportingLedgerStore): Promise<string[]>;
|
|
30
|
+
/** The parts of the scheduler options that failure reporting reads. */
|
|
31
|
+
export interface ReportingSchedulerReportingOptionsV1 {
|
|
32
|
+
onError?: (error: unknown) => void | Promise<void>;
|
|
33
|
+
logger?: {
|
|
34
|
+
warn: (message: string) => void;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/** Where in the scheduler loop a failure happened. */
|
|
38
|
+
export interface ReportingSchedulerFailureSiteV1 {
|
|
39
|
+
readonly phase: 'roster' | 'cycle' | 'maintenance';
|
|
40
|
+
readonly accountId?: string | undefined;
|
|
41
|
+
}
|
|
42
|
+
export declare function reportReportingSchedulerError(options: ReportingSchedulerReportingOptionsV1, signal: AbortSignal, error: unknown, site: ReportingSchedulerFailureSiteV1): Promise<void>;
|
|
43
|
+
export declare function warnReportingSchedulerFailure(options: ReportingSchedulerReportingOptionsV1, site: ReportingSchedulerFailureSiteV1, error: unknown, observerError?: unknown): void;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scheduler primitives shared by `createReliableReportingService` and by services composed with it
|
|
3
|
+
* (for example `@adcp/reporting-storage/service`). They are exported so a composition can pace its own
|
|
4
|
+
* background passes and report failures the same way the Core scheduler does.
|
|
5
|
+
*/
|
|
6
|
+
import type { ReportingLedgerStore } from '../ledger/types';
|
|
7
|
+
/**
|
|
8
|
+
* The error's own message only, credential-redacted, bounded, and total.
|
|
9
|
+
*
|
|
10
|
+
* Stacks and error objects can carry request payloads and upstream credentials
|
|
11
|
+
* into a log sink the adopter did not choose, so only `message` is read. Every
|
|
12
|
+
* step is guarded because the value is arbitrary: `String(Object.create(null))`
|
|
13
|
+
* throws, a `Symbol.toPrimitive` or `message` getter can throw or run adopter
|
|
14
|
+
* code, and a Proxy can trap the prototype walk `instanceof` performs. This
|
|
15
|
+
* function runs while building the diagnostic, outside the catch that guards
|
|
16
|
+
* the logger call, so a throw here escaped `reportSchedulerError`, rejected the
|
|
17
|
+
* scheduler loop, and surfaced as an unhandled rejection — killing the
|
|
18
|
+
* background loop, or the host, over an error object's shape.
|
|
19
|
+
*/
|
|
20
|
+
export declare function reportingSchedulerErrorMessage(error: unknown): string;
|
|
21
|
+
export declare function reportingSchedulerDelay(milliseconds: number, signal: AbortSignal): Promise<void>;
|
|
22
|
+
/** Start each pass one tenant further along so no fixed order can starve. */
|
|
23
|
+
export declare function rotateReportingRoster<T>(values: readonly T[], by: number): T[];
|
|
24
|
+
/**
|
|
25
|
+
* Every account the ledger currently holds a configuration for. This is the
|
|
26
|
+
* roster a deployment-wide worker is authorized over, so it is also the roster
|
|
27
|
+
* the per-account budgets apply to.
|
|
28
|
+
*/
|
|
29
|
+
export declare function reportingDeploymentWideAccountIds(store: ReportingLedgerStore): Promise<string[]>;
|
|
30
|
+
/** The parts of the scheduler options that failure reporting reads. */
|
|
31
|
+
export interface ReportingSchedulerReportingOptionsV1 {
|
|
32
|
+
onError?: (error: unknown) => void | Promise<void>;
|
|
33
|
+
logger?: {
|
|
34
|
+
warn: (message: string) => void;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/** Where in the scheduler loop a failure happened. */
|
|
38
|
+
export interface ReportingSchedulerFailureSiteV1 {
|
|
39
|
+
readonly phase: 'roster' | 'cycle' | 'maintenance';
|
|
40
|
+
readonly accountId?: string | undefined;
|
|
41
|
+
}
|
|
42
|
+
export declare function reportReportingSchedulerError(options: ReportingSchedulerReportingOptionsV1, signal: AbortSignal, error: unknown, site: ReportingSchedulerFailureSiteV1): Promise<void>;
|
|
43
|
+
export declare function warnReportingSchedulerFailure(options: ReportingSchedulerReportingOptionsV1, site: ReportingSchedulerFailureSiteV1, error: unknown, observerError?: unknown): void;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var scheduler_support_exports = {};
|
|
20
|
+
__export(scheduler_support_exports, {
|
|
21
|
+
reportReportingSchedulerError: () => reportReportingSchedulerError,
|
|
22
|
+
reportingDeploymentWideAccountIds: () => reportingDeploymentWideAccountIds,
|
|
23
|
+
reportingSchedulerDelay: () => reportingSchedulerDelay,
|
|
24
|
+
reportingSchedulerErrorMessage: () => reportingSchedulerErrorMessage,
|
|
25
|
+
rotateReportingRoster: () => rotateReportingRoster,
|
|
26
|
+
warnReportingSchedulerFailure: () => warnReportingSchedulerFailure
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(scheduler_support_exports);
|
|
29
|
+
var import_redact_credential_patterns = require('../../utils/redact-credential-patterns.js');
|
|
30
|
+
const MAX_SCHEDULER_MESSAGE_CHARS = 512;
|
|
31
|
+
const MAX_SCHEDULER_SCAN_CHARS = 8192;
|
|
32
|
+
const UNREPORTABLE_SCHEDULER_ERROR = "<unreportable error>";
|
|
33
|
+
function reportingSchedulerErrorMessage(error) {
|
|
34
|
+
try {
|
|
35
|
+
const raw = rawMessage(error);
|
|
36
|
+
const redacted = (0, import_redact_credential_patterns.redactCredentialPatterns)(raw.slice(0, MAX_SCHEDULER_SCAN_CHARS));
|
|
37
|
+
const text = typeof redacted === "string" && redacted.length > 0 ? redacted : UNREPORTABLE_SCHEDULER_ERROR;
|
|
38
|
+
return text.length > MAX_SCHEDULER_MESSAGE_CHARS ? `${text.slice(0, MAX_SCHEDULER_MESSAGE_CHARS)}\u2026` : text;
|
|
39
|
+
} catch {
|
|
40
|
+
return UNREPORTABLE_SCHEDULER_ERROR;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function rawMessage(error) {
|
|
44
|
+
switch (typeof error) {
|
|
45
|
+
case "string":
|
|
46
|
+
return error;
|
|
47
|
+
case "number":
|
|
48
|
+
case "boolean":
|
|
49
|
+
case "bigint":
|
|
50
|
+
return String(error);
|
|
51
|
+
case "undefined":
|
|
52
|
+
return "undefined";
|
|
53
|
+
case "symbol":
|
|
54
|
+
return error.description ?? "symbol";
|
|
55
|
+
default:
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
if (error === null) return "null";
|
|
59
|
+
const message = error.message;
|
|
60
|
+
return typeof message === "string" ? message : "non-Error scheduler failure";
|
|
61
|
+
}
|
|
62
|
+
const MAX_TIMER_DELAY_MILLISECONDS = 2147483647;
|
|
63
|
+
async function reportingSchedulerDelay(milliseconds, signal) {
|
|
64
|
+
let remaining = milliseconds;
|
|
65
|
+
while (remaining > 0 && !signal.aborted) {
|
|
66
|
+
const chunk = Math.min(remaining, MAX_TIMER_DELAY_MILLISECONDS);
|
|
67
|
+
await abortableTimeout(chunk, signal);
|
|
68
|
+
remaining -= chunk;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function abortableTimeout(milliseconds, signal) {
|
|
72
|
+
return new Promise((resolve) => {
|
|
73
|
+
const timer = setTimeout(done, milliseconds);
|
|
74
|
+
function done() {
|
|
75
|
+
clearTimeout(timer);
|
|
76
|
+
signal.removeEventListener("abort", done);
|
|
77
|
+
resolve();
|
|
78
|
+
}
|
|
79
|
+
signal.addEventListener("abort", done, { once: true });
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
function rotateReportingRoster(values, by) {
|
|
83
|
+
if (values.length < 2) return [...values];
|
|
84
|
+
const offset = (by % values.length + values.length) % values.length;
|
|
85
|
+
return [...values.slice(offset), ...values.slice(0, offset)];
|
|
86
|
+
}
|
|
87
|
+
async function reportingDeploymentWideAccountIds(store) {
|
|
88
|
+
const configurations = await store.listConfigurations();
|
|
89
|
+
return [...new Set(configurations.map((value) => value.account.account_id))].sort();
|
|
90
|
+
}
|
|
91
|
+
async function reportReportingSchedulerError(options, signal, error, site) {
|
|
92
|
+
if (signal.aborted) return;
|
|
93
|
+
if (options.onError) {
|
|
94
|
+
try {
|
|
95
|
+
await options.onError(error);
|
|
96
|
+
} catch (observerError) {
|
|
97
|
+
warnReportingSchedulerFailure(options, site, error, observerError);
|
|
98
|
+
}
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
warnReportingSchedulerFailure(options, site, error);
|
|
102
|
+
}
|
|
103
|
+
function warnReportingSchedulerFailure(options, site, error, observerError) {
|
|
104
|
+
const where = site.phase === "roster" ? "could not resolve its account roster, so this pass ran no tenants" : site.phase === "maintenance" ? "ledger maintenance failed; the scheduler continues" : site.accountId === void 0 ? "deployment-wide cycle failed; the scheduler continues" : `cycle failed for account ${site.accountId}; later tenants continue`;
|
|
105
|
+
const observed = observerError === void 0 ? "" : ` (the configured onError also threw: ${reportingSchedulerErrorMessage(observerError)})`;
|
|
106
|
+
const message = `[adcp/reporting] scheduler ${where}: ${reportingSchedulerErrorMessage(error)}${observed}`;
|
|
107
|
+
const logger = options.logger;
|
|
108
|
+
try {
|
|
109
|
+
if (logger !== void 0) logger.warn(message);
|
|
110
|
+
else defaultSchedulerWarn(message);
|
|
111
|
+
} catch {
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function defaultSchedulerWarn(message) {
|
|
115
|
+
console.warn(message);
|
|
116
|
+
}
|
|
117
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
118
|
+
0 && (module.exports = {
|
|
119
|
+
reportReportingSchedulerError,
|
|
120
|
+
reportingDeploymentWideAccountIds,
|
|
121
|
+
reportingSchedulerDelay,
|
|
122
|
+
reportingSchedulerErrorMessage,
|
|
123
|
+
rotateReportingRoster,
|
|
124
|
+
warnReportingSchedulerFailure
|
|
125
|
+
});
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { redactCredentialPatterns } from "../../utils/redact-credential-patterns.mjs";
|
|
2
|
+
const MAX_SCHEDULER_MESSAGE_CHARS = 512;
|
|
3
|
+
const MAX_SCHEDULER_SCAN_CHARS = 8192;
|
|
4
|
+
const UNREPORTABLE_SCHEDULER_ERROR = "<unreportable error>";
|
|
5
|
+
function reportingSchedulerErrorMessage(error) {
|
|
6
|
+
try {
|
|
7
|
+
const raw = rawMessage(error);
|
|
8
|
+
const redacted = redactCredentialPatterns(raw.slice(0, MAX_SCHEDULER_SCAN_CHARS));
|
|
9
|
+
const text = typeof redacted === "string" && redacted.length > 0 ? redacted : UNREPORTABLE_SCHEDULER_ERROR;
|
|
10
|
+
return text.length > MAX_SCHEDULER_MESSAGE_CHARS ? `${text.slice(0, MAX_SCHEDULER_MESSAGE_CHARS)}\u2026` : text;
|
|
11
|
+
} catch {
|
|
12
|
+
return UNREPORTABLE_SCHEDULER_ERROR;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function rawMessage(error) {
|
|
16
|
+
switch (typeof error) {
|
|
17
|
+
case "string":
|
|
18
|
+
return error;
|
|
19
|
+
case "number":
|
|
20
|
+
case "boolean":
|
|
21
|
+
case "bigint":
|
|
22
|
+
return String(error);
|
|
23
|
+
case "undefined":
|
|
24
|
+
return "undefined";
|
|
25
|
+
case "symbol":
|
|
26
|
+
return error.description ?? "symbol";
|
|
27
|
+
default:
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
if (error === null) return "null";
|
|
31
|
+
const message = error.message;
|
|
32
|
+
return typeof message === "string" ? message : "non-Error scheduler failure";
|
|
33
|
+
}
|
|
34
|
+
const MAX_TIMER_DELAY_MILLISECONDS = 2147483647;
|
|
35
|
+
async function reportingSchedulerDelay(milliseconds, signal) {
|
|
36
|
+
let remaining = milliseconds;
|
|
37
|
+
while (remaining > 0 && !signal.aborted) {
|
|
38
|
+
const chunk = Math.min(remaining, MAX_TIMER_DELAY_MILLISECONDS);
|
|
39
|
+
await abortableTimeout(chunk, signal);
|
|
40
|
+
remaining -= chunk;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function abortableTimeout(milliseconds, signal) {
|
|
44
|
+
return new Promise((resolve) => {
|
|
45
|
+
const timer = setTimeout(done, milliseconds);
|
|
46
|
+
function done() {
|
|
47
|
+
clearTimeout(timer);
|
|
48
|
+
signal.removeEventListener("abort", done);
|
|
49
|
+
resolve();
|
|
50
|
+
}
|
|
51
|
+
signal.addEventListener("abort", done, { once: true });
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function rotateReportingRoster(values, by) {
|
|
55
|
+
if (values.length < 2) return [...values];
|
|
56
|
+
const offset = (by % values.length + values.length) % values.length;
|
|
57
|
+
return [...values.slice(offset), ...values.slice(0, offset)];
|
|
58
|
+
}
|
|
59
|
+
async function reportingDeploymentWideAccountIds(store) {
|
|
60
|
+
const configurations = await store.listConfigurations();
|
|
61
|
+
return [...new Set(configurations.map((value) => value.account.account_id))].sort();
|
|
62
|
+
}
|
|
63
|
+
async function reportReportingSchedulerError(options, signal, error, site) {
|
|
64
|
+
if (signal.aborted) return;
|
|
65
|
+
if (options.onError) {
|
|
66
|
+
try {
|
|
67
|
+
await options.onError(error);
|
|
68
|
+
} catch (observerError) {
|
|
69
|
+
warnReportingSchedulerFailure(options, site, error, observerError);
|
|
70
|
+
}
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
warnReportingSchedulerFailure(options, site, error);
|
|
74
|
+
}
|
|
75
|
+
function warnReportingSchedulerFailure(options, site, error, observerError) {
|
|
76
|
+
const where = site.phase === "roster" ? "could not resolve its account roster, so this pass ran no tenants" : site.phase === "maintenance" ? "ledger maintenance failed; the scheduler continues" : site.accountId === void 0 ? "deployment-wide cycle failed; the scheduler continues" : `cycle failed for account ${site.accountId}; later tenants continue`;
|
|
77
|
+
const observed = observerError === void 0 ? "" : ` (the configured onError also threw: ${reportingSchedulerErrorMessage(observerError)})`;
|
|
78
|
+
const message = `[adcp/reporting] scheduler ${where}: ${reportingSchedulerErrorMessage(error)}${observed}`;
|
|
79
|
+
const logger = options.logger;
|
|
80
|
+
try {
|
|
81
|
+
if (logger !== void 0) logger.warn(message);
|
|
82
|
+
else defaultSchedulerWarn(message);
|
|
83
|
+
} catch {
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function defaultSchedulerWarn(message) {
|
|
87
|
+
console.warn(message);
|
|
88
|
+
}
|
|
89
|
+
export {
|
|
90
|
+
reportReportingSchedulerError,
|
|
91
|
+
reportingDeploymentWideAccountIds,
|
|
92
|
+
reportingSchedulerDelay,
|
|
93
|
+
reportingSchedulerErrorMessage,
|
|
94
|
+
rotateReportingRoster,
|
|
95
|
+
warnReportingSchedulerFailure
|
|
96
|
+
};
|
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
"source_sha": "4e553ad955f83b49c7d221ab5c3ff78237ad02e3",
|
|
5
5
|
"source_tarball_sha256": "580656d6466ef9f0d1119985e6726c2efea718dc671e2ad30957fcb2fd54af0f",
|
|
6
6
|
"upstream_adcp_version": "2.5.3",
|
|
7
|
-
"synced_at": "2026-10-
|
|
7
|
+
"synced_at": "2026-10-16T16:11:36.533Z"
|
|
8
8
|
}
|
|
@@ -60,6 +60,10 @@ export declare function buildSignatureBase(components: ReadonlyArray<string>, re
|
|
|
60
60
|
* meaning as in {@link buildSignatureBase}.
|
|
61
61
|
*/
|
|
62
62
|
export declare function buildResponseSignatureBase(components: ReadonlyArray<string>, response: ResponseLike, params: SignatureParams, signatureParamsValue?: string): string;
|
|
63
|
+
/**
|
|
64
|
+
* Serialize the `@signature-params` inner list (RFC 9421 §2.3) with the
|
|
65
|
+
* structured-field serializer, in the canonical AdCP parameter order.
|
|
66
|
+
*/
|
|
63
67
|
export declare function formatSignatureParams(components: ReadonlyArray<string>, params: SignatureParams): string;
|
|
64
68
|
/**
|
|
65
69
|
* Raw non-ASCII bytes in the URL authority (IDN U-label) are a parse-time
|
|
@@ -60,6 +60,10 @@ export declare function buildSignatureBase(components: ReadonlyArray<string>, re
|
|
|
60
60
|
* meaning as in {@link buildSignatureBase}.
|
|
61
61
|
*/
|
|
62
62
|
export declare function buildResponseSignatureBase(components: ReadonlyArray<string>, response: ResponseLike, params: SignatureParams, signatureParamsValue?: string): string;
|
|
63
|
+
/**
|
|
64
|
+
* Serialize the `@signature-params` inner list (RFC 9421 §2.3) with the
|
|
65
|
+
* structured-field serializer, in the canonical AdCP parameter order.
|
|
66
|
+
*/
|
|
63
67
|
export declare function formatSignatureParams(components: ReadonlyArray<string>, params: SignatureParams): string;
|
|
64
68
|
/**
|
|
65
69
|
* Raw non-ASCII bytes in the URL authority (IDN U-label) are a parse-time
|
|
@@ -28,6 +28,7 @@ __export(canonicalize_exports, {
|
|
|
28
28
|
rejectNonAsciiHost: () => rejectNonAsciiHost
|
|
29
29
|
});
|
|
30
30
|
module.exports = __toCommonJS(canonicalize_exports);
|
|
31
|
+
var import_structured_headers = require("structured-headers");
|
|
31
32
|
var import_errors = require('./errors.js');
|
|
32
33
|
const DEFAULT_PARAM_ORDER = [
|
|
33
34
|
"created",
|
|
@@ -37,7 +38,6 @@ const DEFAULT_PARAM_ORDER = [
|
|
|
37
38
|
"alg",
|
|
38
39
|
"tag"
|
|
39
40
|
];
|
|
40
|
-
const STRING_PARAMS = /* @__PURE__ */ new Set(["nonce", "keyid", "alg", "tag"]);
|
|
41
41
|
const SUPPORTED_DERIVED = /* @__PURE__ */ new Set(["@method", "@target-uri", "@authority", "@status"]);
|
|
42
42
|
function canonicalTargetUri(rawUrl, profile = "legacy") {
|
|
43
43
|
const u = parseCanonicalUrl(rawUrl, profile);
|
|
@@ -127,14 +127,17 @@ function buildResponseSignatureBase(components, response, params, signatureParam
|
|
|
127
127
|
return lines.join("\n");
|
|
128
128
|
}
|
|
129
129
|
function formatSignatureParams(components, params) {
|
|
130
|
-
const
|
|
131
|
-
const paramPairs = [];
|
|
130
|
+
const parameters = /* @__PURE__ */ new Map();
|
|
132
131
|
for (const key of DEFAULT_PARAM_ORDER) {
|
|
133
132
|
const raw = params[key];
|
|
134
|
-
if (raw
|
|
135
|
-
|
|
133
|
+
if (raw !== void 0) parameters.set(key, raw);
|
|
134
|
+
}
|
|
135
|
+
try {
|
|
136
|
+
return (0, import_structured_headers.serializeInnerList)([components.map(componentItem), parameters]);
|
|
137
|
+
} catch (error) {
|
|
138
|
+
if (!(error instanceof import_structured_headers.SerializeError)) throw error;
|
|
139
|
+
throw new TypeError(`Signature parameters are not RFC 8941 serializable: ${error.message}`);
|
|
136
140
|
}
|
|
137
|
-
return `(${componentList});${paramPairs.join(";")}`;
|
|
138
141
|
}
|
|
139
142
|
function parseComponentIdentifier(component) {
|
|
140
143
|
if (!component.includes(";")) return { bare: component, requestBound: false };
|
|
@@ -152,9 +155,12 @@ function parseComponentIdentifier(component) {
|
|
|
152
155
|
requestBound: params.includes("req")
|
|
153
156
|
};
|
|
154
157
|
}
|
|
155
|
-
function
|
|
158
|
+
function componentItem(component) {
|
|
156
159
|
const { bare, requestBound } = parseComponentIdentifier(component);
|
|
157
|
-
return
|
|
160
|
+
return [bare, new Map(requestBound ? [["req", true]] : [])];
|
|
161
|
+
}
|
|
162
|
+
function formatComponentIdentifier(component) {
|
|
163
|
+
return (0, import_structured_headers.serializeItem)(componentItem(component));
|
|
158
164
|
}
|
|
159
165
|
function resolveResponseComponentValue(bare, requestBound, response, requestView) {
|
|
160
166
|
if (bare === "@status") {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SerializeError, serializeInnerList, serializeItem } from "structured-headers";
|
|
1
2
|
import { RequestSignatureError } from "./errors.mjs";
|
|
2
3
|
const DEFAULT_PARAM_ORDER = [
|
|
3
4
|
"created",
|
|
@@ -7,7 +8,6 @@ const DEFAULT_PARAM_ORDER = [
|
|
|
7
8
|
"alg",
|
|
8
9
|
"tag"
|
|
9
10
|
];
|
|
10
|
-
const STRING_PARAMS = /* @__PURE__ */ new Set(["nonce", "keyid", "alg", "tag"]);
|
|
11
11
|
const SUPPORTED_DERIVED = /* @__PURE__ */ new Set(["@method", "@target-uri", "@authority", "@status"]);
|
|
12
12
|
function canonicalTargetUri(rawUrl, profile = "legacy") {
|
|
13
13
|
const u = parseCanonicalUrl(rawUrl, profile);
|
|
@@ -97,14 +97,17 @@ function buildResponseSignatureBase(components, response, params, signatureParam
|
|
|
97
97
|
return lines.join("\n");
|
|
98
98
|
}
|
|
99
99
|
function formatSignatureParams(components, params) {
|
|
100
|
-
const
|
|
101
|
-
const paramPairs = [];
|
|
100
|
+
const parameters = /* @__PURE__ */ new Map();
|
|
102
101
|
for (const key of DEFAULT_PARAM_ORDER) {
|
|
103
102
|
const raw = params[key];
|
|
104
|
-
if (raw
|
|
105
|
-
|
|
103
|
+
if (raw !== void 0) parameters.set(key, raw);
|
|
104
|
+
}
|
|
105
|
+
try {
|
|
106
|
+
return serializeInnerList([components.map(componentItem), parameters]);
|
|
107
|
+
} catch (error) {
|
|
108
|
+
if (!(error instanceof SerializeError)) throw error;
|
|
109
|
+
throw new TypeError(`Signature parameters are not RFC 8941 serializable: ${error.message}`);
|
|
106
110
|
}
|
|
107
|
-
return `(${componentList});${paramPairs.join(";")}`;
|
|
108
111
|
}
|
|
109
112
|
function parseComponentIdentifier(component) {
|
|
110
113
|
if (!component.includes(";")) return { bare: component, requestBound: false };
|
|
@@ -122,9 +125,12 @@ function parseComponentIdentifier(component) {
|
|
|
122
125
|
requestBound: params.includes("req")
|
|
123
126
|
};
|
|
124
127
|
}
|
|
125
|
-
function
|
|
128
|
+
function componentItem(component) {
|
|
126
129
|
const { bare, requestBound } = parseComponentIdentifier(component);
|
|
127
|
-
return
|
|
130
|
+
return [bare, new Map(requestBound ? [["req", true]] : [])];
|
|
131
|
+
}
|
|
132
|
+
function formatComponentIdentifier(component) {
|
|
133
|
+
return serializeItem(componentItem(component));
|
|
128
134
|
}
|
|
129
135
|
function resolveResponseComponentValue(bare, requestBound, response, requestView) {
|
|
130
136
|
if (bare === "@status") {
|
|
@@ -2,6 +2,14 @@ export type SfBinaryEncoding = 'rfc8941-base64' | 'legacy-base64url';
|
|
|
2
2
|
/** Select the request-signing binary profile from a trusted endpoint pin. */
|
|
3
3
|
export declare function requestSigningEncodingForVersion(adcpVersion: string): SfBinaryEncoding;
|
|
4
4
|
export declare function computeContentDigest(body: string | Uint8Array, encoding?: SfBinaryEncoding): string;
|
|
5
|
+
/**
|
|
6
|
+
* Serialize a one-member Dictionary whose value is a byte sequence, e.g.
|
|
7
|
+
* `sig1=:...:` in `Signature` or `sha-256=:...:` in `Content-Digest`. The
|
|
8
|
+
* RFC 8941 form comes from the structured-field serializer. The AdCP 3.0/3.1
|
|
9
|
+
* profile wrote byte sequences in unpadded Base64URL, which is not an RFC 8941
|
|
10
|
+
* `sf-binary` and no serializer emits, so that legacy form stays hand-written.
|
|
11
|
+
*/
|
|
12
|
+
export declare function serializeByteSequenceMember(key: string, bytes: Uint8Array | ArrayBuffer, encoding: SfBinaryEncoding): string;
|
|
5
13
|
/**
|
|
6
14
|
* Extract the `sha-256` member from an RFC 9530 Content-Digest header. The
|
|
7
15
|
* header is an RFC 8941 Dictionary and MAY list multiple algorithms; we look
|
|
@@ -2,6 +2,14 @@ export type SfBinaryEncoding = 'rfc8941-base64' | 'legacy-base64url';
|
|
|
2
2
|
/** Select the request-signing binary profile from a trusted endpoint pin. */
|
|
3
3
|
export declare function requestSigningEncodingForVersion(adcpVersion: string): SfBinaryEncoding;
|
|
4
4
|
export declare function computeContentDigest(body: string | Uint8Array, encoding?: SfBinaryEncoding): string;
|
|
5
|
+
/**
|
|
6
|
+
* Serialize a one-member Dictionary whose value is a byte sequence, e.g.
|
|
7
|
+
* `sig1=:...:` in `Signature` or `sha-256=:...:` in `Content-Digest`. The
|
|
8
|
+
* RFC 8941 form comes from the structured-field serializer. The AdCP 3.0/3.1
|
|
9
|
+
* profile wrote byte sequences in unpadded Base64URL, which is not an RFC 8941
|
|
10
|
+
* `sf-binary` and no serializer emits, so that legacy form stays hand-written.
|
|
11
|
+
*/
|
|
12
|
+
export declare function serializeByteSequenceMember(key: string, bytes: Uint8Array | ArrayBuffer, encoding: SfBinaryEncoding): string;
|
|
5
13
|
/**
|
|
6
14
|
* Extract the `sha-256` member from an RFC 9530 Content-Digest header. The
|
|
7
15
|
* header is an RFC 8941 Dictionary and MAY list multiple algorithms; we look
|
|
@@ -24,7 +24,8 @@ __export(content_digest_exports, {
|
|
|
24
24
|
contentDigestUsesEncoding: () => contentDigestUsesEncoding,
|
|
25
25
|
isPaddedStandardBase64: () => isPaddedStandardBase64,
|
|
26
26
|
parseContentDigest: () => parseContentDigest,
|
|
27
|
-
requestSigningEncodingForVersion: () => requestSigningEncodingForVersion
|
|
27
|
+
requestSigningEncodingForVersion: () => requestSigningEncodingForVersion,
|
|
28
|
+
serializeByteSequenceMember: () => serializeByteSequenceMember
|
|
28
29
|
});
|
|
29
30
|
module.exports = __toCommonJS(content_digest_exports);
|
|
30
31
|
var import_crypto = require("crypto");
|
|
@@ -35,9 +36,13 @@ function requestSigningEncodingForVersion(adcpVersion) {
|
|
|
35
36
|
return /^(?:2(?:\.|$)|3\.(?:0|1)(?:\.|-|$)|3$)/.test(normalized) ? "legacy-base64url" : "rfc8941-base64";
|
|
36
37
|
}
|
|
37
38
|
function computeContentDigest(body, encoding = "rfc8941-base64") {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
return serializeByteSequenceMember("sha-256", (0, import_crypto.createHash)("sha256").update(toBuffer(body)).digest(), encoding);
|
|
40
|
+
}
|
|
41
|
+
function serializeByteSequenceMember(key, bytes, encoding) {
|
|
42
|
+
const buf = Buffer.from(bytes);
|
|
43
|
+
if (encoding === "legacy-base64url") return `${key}=:${buf.toString("base64url")}:`;
|
|
44
|
+
const exact = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
|
|
45
|
+
return (0, import_structured_headers.serializeDictionary)(/* @__PURE__ */ new Map([[key, [exact, /* @__PURE__ */ new Map()]]]));
|
|
41
46
|
}
|
|
42
47
|
function parseContentDigest(header) {
|
|
43
48
|
try {
|
|
@@ -81,5 +86,6 @@ function toBuffer(body) {
|
|
|
81
86
|
contentDigestUsesEncoding,
|
|
82
87
|
isPaddedStandardBase64,
|
|
83
88
|
parseContentDigest,
|
|
84
|
-
requestSigningEncodingForVersion
|
|
89
|
+
requestSigningEncodingForVersion,
|
|
90
|
+
serializeByteSequenceMember
|
|
85
91
|
});
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import { createHash, timingSafeEqual } from "crypto";
|
|
2
|
-
import { parseDictionary } from "structured-headers";
|
|
2
|
+
import { parseDictionary, serializeDictionary } from "structured-headers";
|
|
3
3
|
const SHA256_MEMBER_RE = /(?:^|[,\s])sha-256=:([A-Za-z0-9+/_-]+={0,2}):/;
|
|
4
4
|
function requestSigningEncodingForVersion(adcpVersion) {
|
|
5
5
|
const normalized = adcpVersion.trim().replace(/^v/, "");
|
|
6
6
|
return /^(?:2(?:\.|$)|3\.(?:0|1)(?:\.|-|$)|3$)/.test(normalized) ? "legacy-base64url" : "rfc8941-base64";
|
|
7
7
|
}
|
|
8
8
|
function computeContentDigest(body, encoding = "rfc8941-base64") {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
return serializeByteSequenceMember("sha-256", createHash("sha256").update(toBuffer(body)).digest(), encoding);
|
|
10
|
+
}
|
|
11
|
+
function serializeByteSequenceMember(key, bytes, encoding) {
|
|
12
|
+
const buf = Buffer.from(bytes);
|
|
13
|
+
if (encoding === "legacy-base64url") return `${key}=:${buf.toString("base64url")}:`;
|
|
14
|
+
const exact = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
|
|
15
|
+
return serializeDictionary(/* @__PURE__ */ new Map([[key, [exact, /* @__PURE__ */ new Map()]]]));
|
|
12
16
|
}
|
|
13
17
|
function parseContentDigest(header) {
|
|
14
18
|
try {
|
|
@@ -51,5 +55,6 @@ export {
|
|
|
51
55
|
contentDigestUsesEncoding,
|
|
52
56
|
isPaddedStandardBase64,
|
|
53
57
|
parseContentDigest,
|
|
54
|
-
requestSigningEncodingForVersion
|
|
58
|
+
requestSigningEncodingForVersion,
|
|
59
|
+
serializeByteSequenceMember
|
|
55
60
|
};
|
|
@@ -82,6 +82,7 @@ function prepareRequestSignature(request, identity, options = {}) {
|
|
|
82
82
|
const windowSeconds = Math.min(options.windowSeconds ?? 300, import_types.MAX_SIGNATURE_WINDOW_SECONDS);
|
|
83
83
|
const nonce = options.nonce ?? base64UrlRandom(16);
|
|
84
84
|
const label = options.label ?? "sig1";
|
|
85
|
+
assertLabelAndClock(label, now);
|
|
85
86
|
const hasBody = (request.body ?? "").length > 0;
|
|
86
87
|
const binaryEncoding = options.binaryEncoding ?? "legacy-base64url";
|
|
87
88
|
const coverDigest = options.coverContentDigest ?? binaryEncoding === "rfc8941-base64";
|
|
@@ -112,11 +113,8 @@ function prepareRequestSignature(request, identity, options = {}) {
|
|
|
112
113
|
}
|
|
113
114
|
function finalizeRequestSignature(prepared, signature) {
|
|
114
115
|
const headers = { ...prepared.headers };
|
|
115
|
-
const sigB64 = Buffer.from(signature).toString(
|
|
116
|
-
prepared.binaryEncoding === "legacy-base64url" ? "base64url" : "base64"
|
|
117
|
-
);
|
|
118
116
|
headers["Signature-Input"] = `${prepared.label}=${(0, import_canonicalize.formatSignatureParams)(prepared.components, prepared.params)}`;
|
|
119
|
-
headers["Signature"] =
|
|
117
|
+
headers["Signature"] = (0, import_content_digest.serializeByteSequenceMember)(prepared.label, signature, prepared.binaryEncoding);
|
|
120
118
|
return { headers, signatureBase: prepared.base, params: prepared.params };
|
|
121
119
|
}
|
|
122
120
|
function signRequest(request, key, options = {}) {
|
|
@@ -138,6 +136,7 @@ function prepareWebhookSignature(request, identity, options = {}) {
|
|
|
138
136
|
const windowSeconds = Math.min(options.windowSeconds ?? 300, import_types.MAX_SIGNATURE_WINDOW_SECONDS);
|
|
139
137
|
const nonce = options.nonce ?? base64UrlRandom(16);
|
|
140
138
|
const label = options.label ?? "sig1";
|
|
139
|
+
assertLabelAndClock(label, now);
|
|
141
140
|
const headers = { ...flattenHeaders(request.headers) };
|
|
142
141
|
headers["Content-Digest"] = (0, import_content_digest.computeContentDigest)(request.body ?? "", "legacy-base64url");
|
|
143
142
|
const components = [...import_webhook_verifier.WEBHOOK_MANDATORY_COMPONENTS];
|
|
@@ -164,6 +163,7 @@ function prepareResponseSignature(response, identity, options = {}) {
|
|
|
164
163
|
const windowSeconds = Math.min(options.windowSeconds ?? 300, import_types.MAX_SIGNATURE_WINDOW_SECONDS);
|
|
165
164
|
const nonce = options.nonce ?? base64UrlRandom(16);
|
|
166
165
|
const label = options.label ?? "sig1";
|
|
166
|
+
assertLabelAndClock(label, now);
|
|
167
167
|
const hasBody = (response.body ?? "").length > 0;
|
|
168
168
|
const coverDigest = (options.coverContentDigest ?? true) && hasBody;
|
|
169
169
|
const headers = { ...flattenHeaders(response.headers) };
|
|
@@ -192,9 +192,8 @@ function prepareResponseSignature(response, identity, options = {}) {
|
|
|
192
192
|
}
|
|
193
193
|
function finalizeResponseSignature(prepared, signature) {
|
|
194
194
|
const headers = { ...prepared.headers };
|
|
195
|
-
const sigB64 = Buffer.from(signature).toString("base64url");
|
|
196
195
|
headers["Signature-Input"] = `${prepared.label}=${(0, import_canonicalize.formatSignatureParams)(prepared.components, prepared.params)}`;
|
|
197
|
-
headers["Signature"] =
|
|
196
|
+
headers["Signature"] = (0, import_content_digest.serializeByteSequenceMember)(prepared.label, signature, "legacy-base64url");
|
|
198
197
|
return { status: prepared.status, headers, signatureBase: prepared.base, params: prepared.params };
|
|
199
198
|
}
|
|
200
199
|
function signResponse(response, key, options = {}) {
|
|
@@ -214,6 +213,10 @@ function flattenHeaders(headers) {
|
|
|
214
213
|
}
|
|
215
214
|
return out;
|
|
216
215
|
}
|
|
216
|
+
function assertLabelAndClock(label, now) {
|
|
217
|
+
if (!/^[a-z*][a-z0-9_.*-]*$/.test(label)) throw new TypeError(`Signature label "${label}" is not an RFC 8941 key`);
|
|
218
|
+
if (!Number.isSafeInteger(now)) throw new TypeError("Signature clock must return integer epoch seconds");
|
|
219
|
+
}
|
|
217
220
|
function base64UrlRandom(byteLength) {
|
|
218
221
|
return (0, import_crypto.randomBytes)(byteLength).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
219
222
|
}
|