@adcp/sdk 15.6.0 → 15.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/lib/reporting/ledger/handler.js +20 -8
  2. package/dist/lib/reporting/ledger/handler.mjs +20 -8
  3. package/dist/lib/reporting/ledger/postgres.d.mts +11 -0
  4. package/dist/lib/reporting/ledger/postgres.d.ts +11 -0
  5. package/dist/lib/reporting/ledger/postgres.js +12 -0
  6. package/dist/lib/reporting/ledger/postgres.mjs +12 -0
  7. package/dist/lib/reporting/service/index.d.mts +36 -21
  8. package/dist/lib/reporting/service/index.d.ts +36 -21
  9. package/dist/lib/reporting/service/index.js +75 -65
  10. package/dist/lib/reporting/service/index.mjs +79 -64
  11. package/dist/lib/reporting/service/maintenance.d.mts +91 -0
  12. package/dist/lib/reporting/service/maintenance.d.ts +91 -0
  13. package/dist/lib/reporting/service/maintenance.js +140 -0
  14. package/dist/lib/reporting/service/maintenance.mjs +114 -0
  15. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  16. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  17. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  18. package/dist/lib/types/schemas.generated.js +2542 -2542
  19. package/dist/lib/types/schemas.generated.mjs +2542 -2542
  20. package/dist/lib/validation/bidding-policy.js +1 -1
  21. package/dist/lib/validation/bidding-policy.mjs +1 -1
  22. package/dist/lib/validation/budget-allocation.js +1 -1
  23. package/dist/lib/validation/budget-allocation.mjs +1 -1
  24. package/dist/lib/validation/get-products-request.js +3 -3
  25. package/dist/lib/validation/get-products-request.mjs +3 -3
  26. package/dist/lib/validation/sync-creatives.js +9 -13
  27. package/dist/lib/validation/sync-creatives.mjs +9 -13
  28. package/dist/lib/version.d.mts +3 -3
  29. package/dist/lib/version.d.ts +3 -3
  30. package/dist/lib/version.js +3 -3
  31. package/dist/lib/version.mjs +3 -3
  32. package/docs/TYPE-SUMMARY.md +2 -2
  33. package/docs/ZOD-SCHEMAS.md +11 -1
  34. package/docs/guides/REPORTING-LEDGER.md +89 -0
  35. package/docs/guides/REPORTING-OPERATIONS.md +6 -0
  36. package/docs/llms.txt +2 -2
  37. package/docs/migration-14.x-rc-worksheet.md +4 -4
  38. package/package.json +1 -1
@@ -24,7 +24,7 @@ module.exports = __toCommonJS(bidding_policy_exports);
24
24
  var import_zod = require("zod");
25
25
  var import_schemas = require('../types/schemas.generated.js');
26
26
  const BIDDING_CONTROL_KEYS = ["automatic", "bid_amount", "max_bid", "cost_per", "roas"];
27
- const BiddingPolicySchema = import_schemas.BiddingPolicySchema.superRefine((policy, ctx) => {
27
+ const BiddingPolicySchema = /* @__PURE__ */ import_schemas.BiddingPolicySchema.superRefine((policy, ctx) => {
28
28
  const presentControls = BIDDING_CONTROL_KEYS.filter((key) => policy[key] !== void 0);
29
29
  if (presentControls.length === 0) {
30
30
  ctx.addIssue({
@@ -1,7 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import { BiddingPolicySchema as GeneratedBiddingPolicySchema } from "../types/schemas.generated.mjs";
3
3
  const BIDDING_CONTROL_KEYS = ["automatic", "bid_amount", "max_bid", "cost_per", "roas"];
4
- const BiddingPolicySchema = GeneratedBiddingPolicySchema.superRefine((policy, ctx) => {
4
+ const BiddingPolicySchema = /* @__PURE__ */ GeneratedBiddingPolicySchema.superRefine((policy, ctx) => {
5
5
  const presentControls = BIDDING_CONTROL_KEYS.filter((key) => policy[key] !== void 0);
6
6
  if (presentControls.length === 0) {
7
7
  ctx.addIssue({
@@ -23,7 +23,7 @@ __export(budget_allocation_exports, {
23
23
  module.exports = __toCommonJS(budget_allocation_exports);
24
24
  var import_zod = require("zod");
25
25
  var import_schemas = require('../types/schemas.generated.js');
26
- const CanonicalBudgetAllocationSchema = import_schemas.CanonicalBudgetAllocationSchema.superRefine(
26
+ const CanonicalBudgetAllocationSchema = /* @__PURE__ */ import_schemas.CanonicalBudgetAllocationSchema.superRefine(
27
27
  (allocation, ctx) => {
28
28
  if (allocation.mode === "seller_optimized" && allocation.optimization_goals.length === 0) {
29
29
  ctx.addIssue({
@@ -1,6 +1,6 @@
1
1
  import { z } from "zod";
2
2
  import { CanonicalBudgetAllocationSchema as GeneratedCanonicalBudgetAllocationSchema } from "../types/schemas.generated.mjs";
3
- const CanonicalBudgetAllocationSchema = GeneratedCanonicalBudgetAllocationSchema.superRefine(
3
+ const CanonicalBudgetAllocationSchema = /* @__PURE__ */ GeneratedCanonicalBudgetAllocationSchema.superRefine(
4
4
  (allocation, ctx) => {
5
5
  if (allocation.mode === "seller_optimized" && allocation.optimization_goals.length === 0) {
6
6
  ctx.addIssue({
@@ -26,12 +26,12 @@ var import_zod = require("zod");
26
26
  var import_schemas = require('../types/schemas.generated.js');
27
27
  var import_inline_enums = require('../types/inline-enums.generated.js');
28
28
  const LegacyGetProductsRequestSchema = import_schemas.GetProductsRequestSchema;
29
- const canonicalGetProductsFields = import_inline_enums.GetProductsRequest_FieldsValues.filter(
29
+ const canonicalGetProductsFields = /* @__PURE__ */ import_inline_enums.GetProductsRequest_FieldsValues.filter(
30
30
  (field) => field !== "format_ids"
31
31
  );
32
- const GetProductsRequestSchema = import_schemas.GetProductsRequestSchema.safeExtend({
32
+ const GetProductsRequestSchema = /* @__PURE__ */ (() => import_schemas.GetProductsRequestSchema.safeExtend({
33
33
  fields: import_zod.z.array(import_zod.z.enum(canonicalGetProductsFields)).optional()
34
- });
34
+ }))();
35
35
  // Annotate the CommonJS export names for ESM import in node:
36
36
  0 && (module.exports = {
37
37
  GetProductsRequestSchema,
@@ -2,12 +2,12 @@ import { z } from "zod";
2
2
  import { GetProductsRequestSchema as GeneratedGetProductsRequestSchema } from "../types/schemas.generated.mjs";
3
3
  import { GetProductsRequest_FieldsValues } from "../types/inline-enums.generated.mjs";
4
4
  const LegacyGetProductsRequestSchema = GeneratedGetProductsRequestSchema;
5
- const canonicalGetProductsFields = GetProductsRequest_FieldsValues.filter(
5
+ const canonicalGetProductsFields = /* @__PURE__ */ GetProductsRequest_FieldsValues.filter(
6
6
  (field) => field !== "format_ids"
7
7
  );
8
- const GetProductsRequestSchema = GeneratedGetProductsRequestSchema.safeExtend({
8
+ const GetProductsRequestSchema = /* @__PURE__ */ (() => GeneratedGetProductsRequestSchema.safeExtend({
9
9
  fields: z.array(z.enum(canonicalGetProductsFields)).optional()
10
- });
10
+ }))();
11
11
  export {
12
12
  GetProductsRequestSchema,
13
13
  LegacyGetProductsRequestSchema
@@ -26,18 +26,18 @@ __export(sync_creatives_exports, {
26
26
  module.exports = __toCommonJS(sync_creatives_exports);
27
27
  var import_zod = require("zod");
28
28
  var import_schemas = require('../types/schemas.generated.js');
29
- const SyncCreativesActionSchema = import_zod.z.union([
29
+ const SyncCreativesActionSchema = /* @__PURE__ */ (() => import_zod.z.union([
30
30
  import_zod.z.literal("created"),
31
31
  import_zod.z.literal("updated"),
32
32
  import_zod.z.literal("unchanged"),
33
33
  import_zod.z.literal("failed"),
34
34
  import_zod.z.literal("deleted")
35
- ]);
35
+ ]))();
36
36
  const ASSIGNMENT_ERROR_KEY = /^[a-zA-Z0-9_-]+$/;
37
- const HttpUrlSchema = import_zod.z.string().url().refine((v) => /^https?:\/\//i.test(v), {
37
+ const HttpUrlSchema = /* @__PURE__ */ (() => import_zod.z.string().url().refine((v) => /^https?:\/\//i.test(v), {
38
38
  message: "URL must use http(s) scheme"
39
- });
40
- const SyncCreativesItemSchema = import_zod.z.object({
39
+ }))();
40
+ const SyncCreativesItemSchema = /* @__PURE__ */ (() => import_zod.z.object({
41
41
  creative_id: import_zod.z.string(),
42
42
  revision_id: import_schemas.CreativeRevisionIDSchema.optional(),
43
43
  action: SyncCreativesActionSchema,
@@ -72,19 +72,15 @@ const SyncCreativesItemSchema = import_zod.z.object({
72
72
  message: "status is required when localization is present"
73
73
  });
74
74
  }
75
- });
76
- const SyncCreativesSuccessStrictSchema = import_zod.z.object({
75
+ }))();
76
+ const SyncCreativesSuccessStrictSchema = /* @__PURE__ */ (() => import_zod.z.object({
77
77
  dry_run: import_zod.z.boolean().optional(),
78
78
  creatives: import_zod.z.array(SyncCreativesItemSchema),
79
79
  sandbox: import_zod.z.boolean().optional(),
80
80
  context: import_schemas.ContextObjectSchema.optional(),
81
81
  ext: import_schemas.ExtensionObjectSchema.optional()
82
- }).passthrough();
83
- const SyncCreativesResponseStrictSchema = import_zod.z.union([
84
- SyncCreativesSuccessStrictSchema,
85
- import_schemas.SyncCreativesErrorSchema,
86
- import_schemas.SyncCreativesSubmittedSchema
87
- ]);
82
+ }).passthrough())();
83
+ const SyncCreativesResponseStrictSchema = /* @__PURE__ */ (() => import_zod.z.union([SyncCreativesSuccessStrictSchema, import_schemas.SyncCreativesErrorSchema, import_schemas.SyncCreativesSubmittedSchema]))();
88
84
  // Annotate the CommonJS export names for ESM import in node:
89
85
  0 && (module.exports = {
90
86
  SyncCreativesActionSchema,
@@ -11,18 +11,18 @@ import {
11
11
  SyncCreativesErrorSchema,
12
12
  SyncCreativesSubmittedSchema
13
13
  } from "../types/schemas.generated.mjs";
14
- const SyncCreativesActionSchema = z.union([
14
+ const SyncCreativesActionSchema = /* @__PURE__ */ (() => z.union([
15
15
  z.literal("created"),
16
16
  z.literal("updated"),
17
17
  z.literal("unchanged"),
18
18
  z.literal("failed"),
19
19
  z.literal("deleted")
20
- ]);
20
+ ]))();
21
21
  const ASSIGNMENT_ERROR_KEY = /^[a-zA-Z0-9_-]+$/;
22
- const HttpUrlSchema = z.string().url().refine((v) => /^https?:\/\//i.test(v), {
22
+ const HttpUrlSchema = /* @__PURE__ */ (() => z.string().url().refine((v) => /^https?:\/\//i.test(v), {
23
23
  message: "URL must use http(s) scheme"
24
- });
25
- const SyncCreativesItemSchema = z.object({
24
+ }))();
25
+ const SyncCreativesItemSchema = /* @__PURE__ */ (() => z.object({
26
26
  creative_id: z.string(),
27
27
  revision_id: CreativeRevisionIDSchema.optional(),
28
28
  action: SyncCreativesActionSchema,
@@ -57,19 +57,15 @@ const SyncCreativesItemSchema = z.object({
57
57
  message: "status is required when localization is present"
58
58
  });
59
59
  }
60
- });
61
- const SyncCreativesSuccessStrictSchema = z.object({
60
+ }))();
61
+ const SyncCreativesSuccessStrictSchema = /* @__PURE__ */ (() => z.object({
62
62
  dry_run: z.boolean().optional(),
63
63
  creatives: z.array(SyncCreativesItemSchema),
64
64
  sandbox: z.boolean().optional(),
65
65
  context: ContextObjectSchema.optional(),
66
66
  ext: ExtensionObjectSchema.optional()
67
- }).passthrough();
68
- const SyncCreativesResponseStrictSchema = z.union([
69
- SyncCreativesSuccessStrictSchema,
70
- SyncCreativesErrorSchema,
71
- SyncCreativesSubmittedSchema
72
- ]);
67
+ }).passthrough())();
68
+ const SyncCreativesResponseStrictSchema = /* @__PURE__ */ (() => z.union([SyncCreativesSuccessStrictSchema, SyncCreativesErrorSchema, SyncCreativesSubmittedSchema]))();
73
69
  export {
74
70
  SyncCreativesActionSchema,
75
71
  SyncCreativesItemSchema,
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * AdCP SDK library version
3
3
  */
4
- export declare const LIBRARY_VERSION = "15.6.0";
4
+ export declare const LIBRARY_VERSION = "15.7.1";
5
5
  /**
6
6
  * AdCP specification version this library is built for
7
7
  */
@@ -33,10 +33,10 @@ export type AdcpVersion = (typeof COMPATIBLE_ADCP_VERSIONS)[number];
33
33
  * Full version information
34
34
  */
35
35
  export declare const VERSION_INFO: {
36
- readonly library: "15.6.0";
36
+ readonly library: "15.7.1";
37
37
  readonly adcp: "3.2.3";
38
38
  readonly compatibleVersions: readonly ["v2.5", "v2.6", "v3", "3.0.0", "3.0", "3.0.1", "3.0.2", "3.0.3", "3.0.4", "3.0.5", "3.0.6", "3.0.7", "3.0.8", "3.0.9", "3.0.10", "3.0.11", "3.0.12", "3.0.13", "3.0.14", "3.0.15", "3.0.16", "3.0.17", "3.0.18", "3.0.19", "3.0.20", "3.0.21", "3.0.22", "3.0.23", "3.0.24", "3.0.25", "3.1.0", "3.1", "3.1.1", "3.1.2", "3.1.3", "3.1.4", "3.1.5", "3.1.6", "3.1.7", "3.1.8", "3.1.9", "3.1.10", "3.1.11", "3.1.12", "3.1.13", "3.1.14", "3.1.15", "3.1.16", "3.1.17", "3.1.18", "3.1.19", "3.1.20", "3.1.21", "3.1.22", "3.1.23", "3.1.24", "3.2.1", "3.2", "3.2.2", "3.2.3"];
39
- readonly generatedAt: "2026-10-09T11:44:03.363Z";
39
+ readonly generatedAt: "2026-10-10T00:48:09.224Z";
40
40
  };
41
41
  /**
42
42
  * Get the AdCP specification version this library is built for
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * AdCP SDK library version
3
3
  */
4
- export declare const LIBRARY_VERSION = "15.6.0";
4
+ export declare const LIBRARY_VERSION = "15.7.1";
5
5
  /**
6
6
  * AdCP specification version this library is built for
7
7
  */
@@ -33,10 +33,10 @@ export type AdcpVersion = (typeof COMPATIBLE_ADCP_VERSIONS)[number];
33
33
  * Full version information
34
34
  */
35
35
  export declare const VERSION_INFO: {
36
- readonly library: "15.6.0";
36
+ readonly library: "15.7.1";
37
37
  readonly adcp: "3.2.3";
38
38
  readonly compatibleVersions: readonly ["v2.5", "v2.6", "v3", "3.0.0", "3.0", "3.0.1", "3.0.2", "3.0.3", "3.0.4", "3.0.5", "3.0.6", "3.0.7", "3.0.8", "3.0.9", "3.0.10", "3.0.11", "3.0.12", "3.0.13", "3.0.14", "3.0.15", "3.0.16", "3.0.17", "3.0.18", "3.0.19", "3.0.20", "3.0.21", "3.0.22", "3.0.23", "3.0.24", "3.0.25", "3.1.0", "3.1", "3.1.1", "3.1.2", "3.1.3", "3.1.4", "3.1.5", "3.1.6", "3.1.7", "3.1.8", "3.1.9", "3.1.10", "3.1.11", "3.1.12", "3.1.13", "3.1.14", "3.1.15", "3.1.16", "3.1.17", "3.1.18", "3.1.19", "3.1.20", "3.1.21", "3.1.22", "3.1.23", "3.1.24", "3.2.1", "3.2", "3.2.2", "3.2.3"];
39
- readonly generatedAt: "2026-10-09T11:44:03.363Z";
39
+ readonly generatedAt: "2026-10-10T00:48:09.224Z";
40
40
  };
41
41
  /**
42
42
  * Get the AdCP specification version this library is built for
@@ -31,7 +31,7 @@ __export(version_exports, {
31
31
  toReleasePrecisionVersion: () => toReleasePrecisionVersion
32
32
  });
33
33
  module.exports = __toCommonJS(version_exports);
34
- const LIBRARY_VERSION = "15.6.0";
34
+ const LIBRARY_VERSION = "15.7.1";
35
35
  const ADCP_VERSION = "3.2.3";
36
36
  const ADCP_MAJOR_VERSION = 3;
37
37
  const COMPATIBLE_ADCP_VERSIONS = [
@@ -97,10 +97,10 @@ const COMPATIBLE_ADCP_VERSIONS = [
97
97
  "3.2.3"
98
98
  ];
99
99
  const VERSION_INFO = {
100
- library: "15.6.0",
100
+ library: "15.7.1",
101
101
  adcp: "3.2.3",
102
102
  compatibleVersions: COMPATIBLE_ADCP_VERSIONS,
103
- generatedAt: "2026-10-09T11:44:03.363Z"
103
+ generatedAt: "2026-10-10T00:48:09.224Z"
104
104
  };
105
105
  function getAdcpVersion() {
106
106
  return ADCP_VERSION;
@@ -1,4 +1,4 @@
1
- const LIBRARY_VERSION = "15.6.0";
1
+ const LIBRARY_VERSION = "15.7.1";
2
2
  const ADCP_VERSION = "3.2.3";
3
3
  const ADCP_MAJOR_VERSION = 3;
4
4
  const COMPATIBLE_ADCP_VERSIONS = [
@@ -64,10 +64,10 @@ const COMPATIBLE_ADCP_VERSIONS = [
64
64
  "3.2.3"
65
65
  ];
66
66
  const VERSION_INFO = {
67
- library: "15.6.0",
67
+ library: "15.7.1",
68
68
  adcp: "3.2.3",
69
69
  compatibleVersions: COMPATIBLE_ADCP_VERSIONS,
70
- generatedAt: "2026-10-09T11:44:03.363Z"
70
+ generatedAt: "2026-10-10T00:48:09.224Z"
71
71
  };
72
72
  function getAdcpVersion() {
73
73
  return ADCP_VERSION;
@@ -1,7 +1,7 @@
1
1
  # AdCP Type Summary
2
2
 
3
- > Generated at: 2026-10-09
4
- > @adcp/sdk v15.6.0
3
+ > Generated at: 2026-10-10
4
+ > @adcp/sdk v15.7.1
5
5
 
6
6
  Curated reference of the types that matter for using the AdCP client. For full generated types see `src/lib/types/tools.generated.ts` and `src/lib/types/core.generated.ts`.
7
7
 
@@ -30,7 +30,17 @@ import { EventSourceHealthSchema } from '@adcp/sdk/schemas/browser';
30
30
  const health = EventSourceHealthSchema.parse(rawHealth);
31
31
  ```
32
32
 
33
- This entry has no Node built-ins in its import graph and shares the Node entry's portable validators, including canonical and legacy get-products selectors. JSON Schema loading and tool registration helpers are available from `@adcp/sdk/schemas`. Importing one schema can still retain the full generated module; per-schema tree-shaking is tracked in [#3178](https://github.com/adcontextprotocol/adcp-client/issues/3178).
33
+ This entry has no Node built-ins in its import graph and shares the Node entry's portable validators, including canonical and legacy get-products selectors. Named ESM imports let bundlers remove unused validators while preserving the selected schema's dependencies. JSON Schema loading and tool registration helpers are available from `@adcp/sdk/schemas`.
34
+
35
+ `npm run test:schemas-browser` bundles a single `EventSourceHealthSchema` import with esbuild (`platform: 'browser'`, `format: 'iife'`, `target: 'es2022'`, `minify: true`). The standalone bundle includes Zod and ajv-formats, with no external dependencies. Measurements for esbuild 0.28.2 and Zod 4.4.3:
36
+
37
+ | Measure | Before tree-shaking | With pure schema initializers | CI maximum |
38
+ | --- | ---: | ---: | ---: |
39
+ | Minified bundle | 1,539,250 B | 336,182 B | 375,000 B |
40
+ | Gzipped bundle | 265,418 B | 67,420 B | 75,000 B |
41
+ | Generated validators retained | 1,203,529 B | 744 B | 2,048 B |
42
+
43
+ The total-size limits leave roughly 11% headroom for dependency changes. The separate generated-code limit catches unrelated validators being retained even if dependencies become smaller. The check also verifies that product, media-buy, and reporting-obligation validators disappear and that the bundled schema still validates without Node globals. Existing tests exercise all exports through ESM and CommonJS, declaration paths, and portable cross-field validation.
34
44
 
35
45
  ## Why Zod Schemas?
36
46
 
@@ -307,6 +307,11 @@ await store.readyRowStorage();
307
307
  - Missing or corrupt rows inside the retention window make
308
308
  `get_media_buy_delivery` fail with `SERVICE_UNAVAILABLE` rather than reporting
309
309
  the revision as absent; expired rows read like an unknown revision.
310
+ - An exact `get_media_buy_delivery` read of an unknown, unauthorized, expired or
311
+ compacted revision, or with a tampered `pagination.cursor`, returns the same
312
+ nondisclosing `REFERENCE_NOT_FOUND` with `field: "reporting_revision_id"`
313
+ (not transient, so buyers do not retry), so a response never reveals whether a
314
+ revision exists for another account.
310
315
  - Managed Delivery claims hydrate PostgreSQL-stored rows automatically.
311
316
 
312
317
  To move existing inline rows into row storage, run the resumable migration in
@@ -541,6 +546,90 @@ because the retired obligations no longer exist.
541
546
  always sweeps abandoned row uploads and expired cursor snapshots and
542
547
  checkpoints, and retires periods when retention is enabled.
543
548
 
549
+ ### Core-only setup with row storage, change feed and retention
550
+
551
+ You do not need the production service (managed delivery, notifications and
552
+ activity) to keep a ledger tidy. Build the store with the options you want and
553
+ give `createReliableReportingService` a `maintenance` option. The production
554
+ service does the same work automatically; the two share one implementation, so
555
+ partial-failure reporting, the `maxFeedHoldDays` that retention honours, per-task
556
+ limits and abort handling are identical.
557
+
558
+ ```ts
559
+ import {
560
+ PostgresReportingLedgerStore,
561
+ REPORTING_LEDGER_MIGRATION,
562
+ REPORTING_ROW_STORAGE_MIGRATION,
563
+ REPORTING_LEDGER_CHANGES_MIGRATION,
564
+ } from '@adcp/sdk/reporting/ledger';
565
+ import { createReliableReportingService } from '@adcp/sdk/reporting/service';
566
+
567
+ // Apply the three migrations, then:
568
+ const store = new PostgresReportingLedgerStore(pool, {
569
+ acknowledgeIsolatedDatabase: true,
570
+ rowStorage, // verified chunked rows in your object store
571
+ changeFeed: true, // host reads and consumer cursors
572
+ });
573
+ await store.readyRowStorage();
574
+
575
+ const reporting = createReliableReportingService({
576
+ store,
577
+ statusRetentionDays: 90, // the commitment advertised to buyers; retention uses it
578
+ // ...adapters, contact, resolveSource, resolveCurrency, resolveCoverage
579
+ maintenance: {
580
+ intervalMilliseconds: 300_000, // default: at most one pass per 5 minutes
581
+ retention: { enabled: true, recordRetentionDays: 120, limit: 100 },
582
+ changeFeed: { changeRetentionDays: 30, maxFeedHoldDays: 7 },
583
+ },
584
+ });
585
+
586
+ reporting.start({ intervalMilliseconds: 60_000, deploymentWide: true, onError });
587
+ ```
588
+
589
+ `reporting.start()` runs maintenance on its first pass and then at most once per
590
+ `maintenance.intervalMilliseconds`, after the tenant cycles, never on every
591
+ cycle. A task that throws, or that resolves with `failed` items, goes to the
592
+ scheduler's `onError` (or `logger.warn`) and never stops the loop; partial
593
+ failures arrive as `ReportingMaintenancePartialFailureError`.
594
+
595
+ If you run your own scheduler instead, call `reporting.runMaintenance({ signal })`.
596
+ It returns one result per task and reports failures in the result rather than
597
+ throwing:
598
+
599
+ ```ts
600
+ for (const result of await reporting.runMaintenance()) {
601
+ if (result.status === 'failed') log.error(result.task, result.error);
602
+ else if (result.partialFailure) log.warn(result.partialFailure.message);
603
+ }
604
+ ```
605
+
606
+ Tasks, in order:
607
+
608
+ | Task | Runs | What it does |
609
+ | --------------------- | ------------------------------------------------- | -------------------------------------------------------------------- |
610
+ | `snapshot sweep` | always | Deletes expired cursor snapshots and checkpoints (1,000 per pass). |
611
+ | `row upload sweep` | always | Resolves abandoned object uploads (100 per pass); no-op without row storage. |
612
+ | `change-feed pruning` | when `maintenance.changeFeed` is set | `pruneChanges` with `changeRetentionDays` and `maxFeedHoldDays`. |
613
+ | `retention` | when `maintenance.retention.enabled` is `true` | `retireExpiredPeriods` with the service's `statusRetentionDays` and the feed's `maxFeedHoldDays`. |
614
+
615
+ Notes:
616
+
617
+ - `maintenance` requires a `PostgresReportingLedgerStore` (or a store with the
618
+ same `retireExpiredPeriods`, `pruneChanges` and `sweepRowWriteIntents`
619
+ methods) and fails at construction otherwise. `maintenance.changeFeed` also
620
+ requires `changeFeed: true` on the store, since pruning is otherwise a silent
621
+ no-op.
622
+ - Retention takes `statusRetentionDays` from the service, so it can never retire
623
+ a period earlier than the retention you advertise. `recordRetentionDays` may
624
+ only lengthen it.
625
+ - The snapshot sweep uses `store.sweepExpiredState()`. A custom store without
626
+ that method skips the task rather than failing.
627
+ - Run it on every replica or on one: each task is bounded, resumable and safe
628
+ to run concurrently.
629
+ - Enable `retention` last (see the adoption checklist in the
630
+ [operations guide](REPORTING-OPERATIONS.md#adopting-row-storage-retention-and-the-change-feed)).
631
+ Retirement cannot be undone.
632
+
544
633
  ### Host reads: current revisions and the change feed
545
634
 
546
635
  In-process consumers such as pacing, alerts and warehouse loaders read from the
@@ -78,6 +78,12 @@ Each of these features is opt-in and additive. Enable them one at a time on a
78
78
  running deployment. See the [ledger guide](REPORTING-LEDGER.md#row-storage)
79
79
  for configuration details.
80
80
 
81
+ Running Core only, without the production service? Pass `maintenance` to
82
+ `createReliableReportingService` so its scheduler (or `runMaintenance()`) does
83
+ the retention, change-feed pruning and abandoned-upload sweeps the production
84
+ service runs for you. See
85
+ [Core-only setup](REPORTING-LEDGER.md#core-only-setup-with-row-storage-change-feed-and-retention).
86
+
81
87
  1. **Row storage.** Apply `REPORTING_ROW_STORAGE_MIGRATION` (PostgreSQL 13+),
82
88
  or pass `rowStorage` to the production service, which adds it to
83
89
  `setup.migrations`. Roll out with `rowStorage` set. New revisions store
package/docs/llms.txt CHANGED
@@ -1,7 +1,7 @@
1
1
  # Ad Context Protocol (AdCP)
2
2
 
3
- > Generated at: 2026-10-09
4
- > Library: @adcp/sdk v15.6.0
3
+ > Generated at: 2026-10-10
4
+ > Library: @adcp/sdk v15.7.1
5
5
  > AdCP major version: 3
6
6
  > Canonical URL: https://adcontextprotocol.github.io/adcp-client/llms.txt
7
7
  > Note: the `Library` stamp reflects the package.json version at doc-generation time. The narrative below describes the surface that lands on the next-published minor — including any 6.7 helpers documented here ahead of the release tag.
@@ -11,8 +11,8 @@ below as the publication/deployment gate.
11
11
 
12
12
  | Fact | Value |
13
13
  | --- | --- |
14
- | Exact npm package | `@adcp/sdk@15.6.0` |
15
- | npm integrity | registry-derived after publication; run `npm view @adcp/sdk@15.6.0 dist.integrity` |
14
+ | Exact npm package | `@adcp/sdk@15.7.1` |
15
+ | npm integrity | registry-derived after publication; run `npm view @adcp/sdk@15.7.1 dist.integrity` |
16
16
  | Node.js runtime | `^20.19.0 || >=22.12.0` |
17
17
  | Default AdCP wire release | `3.2.3` |
18
18
  | Maintained wire releases | `v2.5`, `v2.6`, `v3`, `3.0.0`, `3.0`, `3.0.1`, `3.0.2`, `3.0.3`, `3.0.4`, `3.0.5`, `3.0.6`, `3.0.7`, `3.0.8`, `3.0.9`, `3.0.10`, `3.0.11`, `3.0.12`, `3.0.13`, `3.0.14`, `3.0.15`, `3.0.16`, `3.0.17`, `3.0.18`, `3.0.19`, `3.0.20`, `3.0.21`, `3.0.22`, `3.0.23`, `3.0.24`, `3.0.25`, `3.1.0`, `3.1`, `3.1.1`, `3.1.2`, `3.1.3`, `3.1.4`, `3.1.5`, `3.1.6`, `3.1.7`, `3.1.8`, `3.1.9`, `3.1.10`, `3.1.11`, `3.1.12`, `3.1.13`, `3.1.14`, `3.1.15`, `3.1.16`, `3.1.17`, `3.1.18`, `3.1.19`, `3.1.20`, `3.1.21`, `3.1.22`, `3.1.23`, `3.1.24`, `3.2.1`, `3.2`, `3.2.2`, `3.2.3` |
@@ -21,8 +21,8 @@ below as the publication/deployment gate.
21
21
  Install exact production inputs rather than a moving range or dist-tag:
22
22
 
23
23
  ```bash
24
- npm install --save-exact '@adcp/sdk@15.6.0'
25
- npm view '@adcp/sdk@15.6.0' dist.integrity
24
+ npm install --save-exact '@adcp/sdk@15.7.1'
25
+ npm view '@adcp/sdk@15.7.1' dist.integrity
26
26
  ```
27
27
 
28
28
  ### Required and optional peers
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adcp/sdk",
3
- "version": "15.6.0",
3
+ "version": "15.7.1",
4
4
  "description": "AdCP SDK — client, server, and compliance harnesses for the AdContext Protocol (MCP + A2A)",
5
5
  "workspaces": [
6
6
  ".",