@plasius/economy 0.9.0 → 0.11.0

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/index.js CHANGED
@@ -1903,6 +1903,7 @@ var COMMAND_SOURCES = /* @__PURE__ */ new Set([
1903
1903
  "shopify",
1904
1904
  "ayet",
1905
1905
  "bitlabs",
1906
+ "google-ad-manager",
1906
1907
  "operator",
1907
1908
  "system"
1908
1909
  ]);
@@ -1915,7 +1916,8 @@ var PRINCIPAL_TYPES = /* @__PURE__ */ new Set([
1915
1916
  var PROVIDER_SOURCES = /* @__PURE__ */ new Set([
1916
1917
  "shopify",
1917
1918
  "ayet",
1918
- "bitlabs"
1919
+ "bitlabs",
1920
+ "google-ad-manager"
1919
1921
  ]);
1920
1922
  var CAUSATION_KINDS = /* @__PURE__ */ new Set([
1921
1923
  "provider-event",
@@ -1927,10 +1929,12 @@ var CAUSATION_KINDS = /* @__PURE__ */ new Set([
1927
1929
  var PROVIDERS = /* @__PURE__ */ new Set([
1928
1930
  "shopify",
1929
1931
  "ayet",
1930
- "bitlabs"
1932
+ "bitlabs",
1933
+ "google-ad-manager"
1931
1934
  ]);
1932
1935
  var FINGERPRINT_DOMAINS = /* @__PURE__ */ new Set([
1933
1936
  "economy.idempotency-key.v1",
1937
+ "economy.google-reporting-key.v1",
1934
1938
  "economy.provider-event-key.v1",
1935
1939
  "economy.provider-object-key.v1",
1936
1940
  "economy.provider-payload.v1",
@@ -1956,6 +1960,12 @@ var SOURCE_COMMAND_TYPES = {
1956
1960
  ]),
1957
1961
  ayet: /* @__PURE__ */ new Set(["credit-reward", "hold", "release-hold", "reverse"]),
1958
1962
  bitlabs: /* @__PURE__ */ new Set(["credit-reward", "hold", "release-hold", "reverse"]),
1963
+ "google-ad-manager": /* @__PURE__ */ new Set([
1964
+ "credit-reward",
1965
+ "hold",
1966
+ "release-hold",
1967
+ "reverse"
1968
+ ]),
1959
1969
  operator: /* @__PURE__ */ new Set(["adjust", "reverse", "hold", "release-hold"]),
1960
1970
  system: /* @__PURE__ */ new Set([
1961
1971
  "credit-event",
@@ -2229,6 +2239,9 @@ function assertEconomyProviderEvidenceHash(evidence) {
2229
2239
  "reconciliationEvidenceFingerprint",
2230
2240
  "signatureScheme",
2231
2241
  "signatureVerifiedAt",
2242
+ "verificationMode",
2243
+ "authenticatedRetrievalScheme",
2244
+ "authenticatedRetrievedAt",
2232
2245
  "providerOccurredAt",
2233
2246
  "receivedAt",
2234
2247
  "operationalHandleBindingId"
@@ -2263,9 +2276,27 @@ function assertEconomyProviderEvidenceHash(evidence) {
2263
2276
  );
2264
2277
  }
2265
2278
  assertSafeClassifier(evidence.eventType, "Provider event type");
2266
- assertSafeClassifier(evidence.signatureScheme, "Provider signature scheme");
2267
- const signatureVerifiedAt = parseIsoTimestamp(evidence.signatureVerifiedAt);
2268
2279
  const receivedAt = parseIsoTimestamp(evidence.receivedAt);
2280
+ const signatureFieldsPresent = evidence.signatureScheme !== void 0 && evidence.signatureVerifiedAt !== void 0;
2281
+ const retrievalFieldsPresent = evidence.authenticatedRetrievalScheme !== void 0 && evidence.authenticatedRetrievedAt !== void 0;
2282
+ const verificationMode = evidence.verificationMode ?? "provider-signature";
2283
+ economyAssert(
2284
+ verificationMode === "provider-signature" && evidence.provider !== "google-ad-manager" && signatureFieldsPresent && !retrievalFieldsPresent && evidence.authenticatedRetrievalScheme === void 0 && evidence.authenticatedRetrievedAt === void 0 || verificationMode === "authenticated-retrieval" && evidence.provider === "google-ad-manager" && retrievalFieldsPresent && evidence.signatureScheme === void 0 && evidence.signatureVerifiedAt === void 0,
2285
+ "INVALID_CONTRACT",
2286
+ "Provider evidence must use exactly one permitted verification method"
2287
+ );
2288
+ const verifiedAt = verificationMode === "provider-signature" ? evidence.signatureVerifiedAt : evidence.authenticatedRetrievedAt;
2289
+ if (verificationMode === "provider-signature") {
2290
+ assertSafeClassifier(
2291
+ evidence.signatureScheme,
2292
+ "Provider signature scheme"
2293
+ );
2294
+ } else {
2295
+ assertSafeClassifier(
2296
+ evidence.authenticatedRetrievalScheme,
2297
+ "Provider authenticated-retrieval scheme"
2298
+ );
2299
+ }
2269
2300
  if (evidence.providerOccurredAt !== void 0) {
2270
2301
  economyAssert(
2271
2302
  parseIsoTimestamp(evidence.providerOccurredAt) <= receivedAt,
@@ -2274,9 +2305,9 @@ function assertEconomyProviderEvidenceHash(evidence) {
2274
2305
  );
2275
2306
  }
2276
2307
  economyAssert(
2277
- receivedAt >= signatureVerifiedAt,
2308
+ receivedAt >= parseIsoTimestamp(verifiedAt),
2278
2309
  "INVALID_TIME_WINDOW",
2279
- "Provider evidence cannot be received before signature verification"
2310
+ "Provider evidence cannot be received before verification"
2280
2311
  );
2281
2312
  if (evidence.operationalHandleBindingId !== void 0) {
2282
2313
  assertEconomyIdentifier(
@@ -2626,8 +2657,13 @@ function canonicalEconomyProviderEvidenceHashPayload(evidence) {
2626
2657
  evidence.reconciliationEvidenceFingerprint
2627
2658
  )
2628
2659
  },
2629
- signatureScheme: evidence.signatureScheme,
2630
- signatureVerifiedAt: evidence.signatureVerifiedAt,
2660
+ ...evidence.verificationMode === void 0 ? {} : { verificationMode: evidence.verificationMode },
2661
+ ...evidence.signatureScheme === void 0 ? {} : { signatureScheme: evidence.signatureScheme },
2662
+ ...evidence.signatureVerifiedAt === void 0 ? {} : { signatureVerifiedAt: evidence.signatureVerifiedAt },
2663
+ ...evidence.authenticatedRetrievalScheme === void 0 ? {} : {
2664
+ authenticatedRetrievalScheme: evidence.authenticatedRetrievalScheme
2665
+ },
2666
+ ...evidence.authenticatedRetrievedAt === void 0 ? {} : { authenticatedRetrievedAt: evidence.authenticatedRetrievedAt },
2631
2667
  ...evidence.providerOccurredAt === void 0 ? {} : { providerOccurredAt: evidence.providerOccurredAt },
2632
2668
  receivedAt: evidence.receivedAt,
2633
2669
  ...evidence.operationalHandleBindingId === void 0 ? {} : {
@@ -3441,6 +3477,7 @@ var ACTIVITY_SOURCES2 = /* @__PURE__ */ new Set([
3441
3477
  "shopify",
3442
3478
  "ayet",
3443
3479
  "bitlabs",
3480
+ "google-ad-manager",
3444
3481
  "subscription",
3445
3482
  "event",
3446
3483
  "competition",
@@ -3680,6 +3717,15 @@ function assertReversalAvailable(originalTransactionId, existingTransactions) {
3680
3717
  }
3681
3718
 
3682
3719
  // src/audit-graph.ts
3720
+ var PROVIDER_COMMAND_SOURCES = /* @__PURE__ */ new Set([
3721
+ "shopify",
3722
+ "ayet",
3723
+ "bitlabs",
3724
+ "google-ad-manager"
3725
+ ]);
3726
+ function isProviderCommandSource(source) {
3727
+ return PROVIDER_COMMAND_SOURCES.has(source);
3728
+ }
3683
3729
  function assertCanonicalHash4(value, label) {
3684
3730
  economyAssert(
3685
3731
  typeof value === "string" && /^sha256:[a-f0-9]{64}$/u.test(value),
@@ -3707,7 +3753,7 @@ function assertCreatedReference(manifest, kind, id, contentHash) {
3707
3753
  }
3708
3754
  function assertProviderGraph(graph, hash, acceptanceCommit) {
3709
3755
  const envelope = graph.commandEnvelope;
3710
- const providerSource = envelope.commandSource === "shopify" || envelope.commandSource === "ayet" || envelope.commandSource === "bitlabs";
3756
+ const providerSource = isProviderCommandSource(envelope.commandSource);
3711
3757
  if (!providerSource) {
3712
3758
  economyAssert(
3713
3759
  graph.providerEvidenceManifest === void 0 && graph.providerEvidence.length === 0 && graph.operationalHandleBindings.length === 0,
@@ -3854,7 +3900,7 @@ function expectedTransactionActivityTypes(envelope) {
3854
3900
  }
3855
3901
  if (envelope.commandType === "credit-reward") {
3856
3902
  return /* @__PURE__ */ new Set([
3857
- envelope.commandSource === "ayet" ? "rewarded-ad" : "offerwall"
3903
+ envelope.commandSource === "ayet" || envelope.commandSource === "google-ad-manager" ? "rewarded-ad" : "offerwall"
3858
3904
  ]);
3859
3905
  }
3860
3906
  if (envelope.commandType === "credit-event") {
@@ -3909,7 +3955,7 @@ function assertReceiptGraph(graph, commandEnvelopeHash, hash, acceptanceCommit,
3909
3955
  accepted.receiptId,
3910
3956
  acceptedHash
3911
3957
  );
3912
- const providerSource = envelope.commandSource === "shopify" || envelope.commandSource === "ayet" || envelope.commandSource === "bitlabs";
3958
+ const providerSource = isProviderCommandSource(envelope.commandSource);
3913
3959
  if (graph.resultReceipt === void 0) {
3914
3960
  economyAssert(
3915
3961
  providerSource && graph.transaction === void 0 && resultCommit === void 0,
@@ -4029,7 +4075,9 @@ function assertAuthorityCommits(graph, hash) {
4029
4075
  "INVALID_CONTRACT",
4030
4076
  "Authority commits do not reconstruct the expected authority head"
4031
4077
  );
4032
- const providerSource = graph.commandEnvelope.commandSource === "shopify" || graph.commandEnvelope.commandSource === "ayet" || graph.commandEnvelope.commandSource === "bitlabs";
4078
+ const providerSource = isProviderCommandSource(
4079
+ graph.commandEnvelope.commandSource
4080
+ );
4033
4081
  const acceptanceKind = providerSource ? "provider-acceptance" : "first-party-command";
4034
4082
  const acceptanceCommit = graph.commits.find(
4035
4083
  (commit) => commit.manifest.commitKind === acceptanceKind
@@ -4234,6 +4282,324 @@ function evaluateEarlyBackerBySettlementV2(payerAccountId, receivingHouseholdId,
4234
4282
  };
4235
4283
  }
4236
4284
 
4285
+ // src/google-rewarded-web.ts
4286
+ var GOOGLE_REWARDED_WEB_PROVIDER = "google-ad-manager";
4287
+ var GOOGLE_REWARDED_WEB_NOMINAL_MICROS_PER_TOKEN = 100000n;
4288
+ var GOOGLE_REWARDED_WEB_MINIMUM_NET_MICROS_PER_TOKEN = 125000n;
4289
+ var SIGNED_BIGINT_MAX = 2n ** 63n - 1n;
4290
+ var CANONICAL_UNSIGNED_INTEGER = /^(?:0|[1-9][0-9]*)$/u;
4291
+ var SHA256 = /^sha256:[a-f0-9]{64}$/u;
4292
+ function assertExactKeys4(value, allowed, label) {
4293
+ economyAssert(
4294
+ Object.keys(value).every((key) => allowed.has(key)) && [...allowed].every(
4295
+ (key) => key === "effectiveUntil" || Object.prototype.hasOwnProperty.call(value, key)
4296
+ ),
4297
+ "INVALID_CONTRACT",
4298
+ `${label} contains missing or unsupported fields`
4299
+ );
4300
+ }
4301
+ function parseGbpMicros(value, label) {
4302
+ economyAssert(
4303
+ typeof value === "string" && CANONICAL_UNSIGNED_INTEGER.test(value),
4304
+ "INVALID_CONTRACT",
4305
+ `${label} must be canonical non-negative GBP micros`
4306
+ );
4307
+ const parsed = BigInt(value);
4308
+ economyAssert(
4309
+ parsed <= SIGNED_BIGINT_MAX,
4310
+ "AMOUNT_OUT_OF_RANGE",
4311
+ `${label} is outside the signed 64-bit range`
4312
+ );
4313
+ return parsed;
4314
+ }
4315
+ function assertRewardPayload(payload) {
4316
+ assertExactKeys4(payload, /* @__PURE__ */ new Set(["type", "amount"]), "Reward payload");
4317
+ economyAssert(
4318
+ payload.type === "plasius-token-progress" && payload.amount === 1,
4319
+ "INVALID_CONTRACT",
4320
+ "Reward payload must disclose exactly one Token of bundle progress"
4321
+ );
4322
+ }
4323
+ function assertBoundedCount(value, label) {
4324
+ economyAssert(
4325
+ Number.isSafeInteger(value) && value >= 0,
4326
+ "INVALID_CONTRACT",
4327
+ `${label} must be a non-negative safe integer`
4328
+ );
4329
+ }
4330
+ function createGoogleRewardedWebQuote(input) {
4331
+ const gross = parseGbpMicros(
4332
+ input.grossRevenueFloorMicros,
4333
+ "grossRevenueFloorMicros"
4334
+ );
4335
+ const providerFee = parseGbpMicros(
4336
+ input.providerFeeMicros,
4337
+ "providerFeeMicros"
4338
+ );
4339
+ const invalidTrafficHaircut = parseGbpMicros(
4340
+ input.invalidTrafficHaircutMicros,
4341
+ "invalidTrafficHaircutMicros"
4342
+ );
4343
+ const otherCost = parseGbpMicros(input.otherCostMicros, "otherCostMicros");
4344
+ const deductions = providerFee + invalidTrafficHaircut + otherCost;
4345
+ economyAssert(
4346
+ deductions <= gross,
4347
+ "INVALID_CONTRACT",
4348
+ "Rewarded-web costs cannot exceed the gross revenue floor"
4349
+ );
4350
+ const eligibleNet = gross - deductions;
4351
+ const retainedMargin = eligibleNet - GOOGLE_REWARDED_WEB_NOMINAL_MICROS_PER_TOKEN;
4352
+ const quote = {
4353
+ schemaVersion: ECONOMY_CONTRACT_VERSION,
4354
+ quoteVersion: input.quoteVersion,
4355
+ provider: GOOGLE_REWARDED_WEB_PROVIDER,
4356
+ currency: "GBP",
4357
+ bundleCompletions: input.bundleCompletions,
4358
+ rewardPayload: input.rewardPayload,
4359
+ grossRevenueFloorMicros: gross.toString(10),
4360
+ providerFeeMicros: providerFee.toString(10),
4361
+ invalidTrafficHaircutMicros: invalidTrafficHaircut.toString(10),
4362
+ otherCostMicros: otherCost.toString(10),
4363
+ eligibleNetRevenueMicros: eligibleNet.toString(10),
4364
+ tokenAmount: serializeTokenSubunits(TOKEN_SUBUNITS_PER_TOKEN),
4365
+ nominalLiabilityMicros: GOOGLE_REWARDED_WEB_NOMINAL_MICROS_PER_TOKEN.toString(10),
4366
+ retainedMarginMicros: retainedMargin.toString(10),
4367
+ effectiveFrom: input.effectiveFrom,
4368
+ ...input.effectiveUntil === void 0 ? {} : { effectiveUntil: input.effectiveUntil }
4369
+ };
4370
+ assertGoogleRewardedWebQuote(quote);
4371
+ return Object.freeze(quote);
4372
+ }
4373
+ function assertGoogleRewardedWebQuote(quote) {
4374
+ assertExactKeys4(
4375
+ quote,
4376
+ /* @__PURE__ */ new Set([
4377
+ "schemaVersion",
4378
+ "quoteVersion",
4379
+ "provider",
4380
+ "currency",
4381
+ "bundleCompletions",
4382
+ "rewardPayload",
4383
+ "grossRevenueFloorMicros",
4384
+ "providerFeeMicros",
4385
+ "invalidTrafficHaircutMicros",
4386
+ "otherCostMicros",
4387
+ "eligibleNetRevenueMicros",
4388
+ "tokenAmount",
4389
+ "nominalLiabilityMicros",
4390
+ "retainedMarginMicros",
4391
+ "effectiveFrom",
4392
+ "effectiveUntil"
4393
+ ]),
4394
+ "Google rewarded-web quote"
4395
+ );
4396
+ economyAssert(
4397
+ quote.schemaVersion === ECONOMY_CONTRACT_VERSION && quote.provider === GOOGLE_REWARDED_WEB_PROVIDER && quote.currency === "GBP",
4398
+ "INVALID_CONTRACT",
4399
+ "Unsupported Google rewarded-web quote contract"
4400
+ );
4401
+ assertEconomyIdentifier(quote.quoteVersion, "quoteVersion");
4402
+ economyAssert(
4403
+ Number.isSafeInteger(quote.bundleCompletions) && quote.bundleCompletions >= 1 && quote.bundleCompletions <= 1e3,
4404
+ "INVALID_CONTRACT",
4405
+ "Bundle completions must be between 1 and 1,000"
4406
+ );
4407
+ assertRewardPayload(quote.rewardPayload);
4408
+ const gross = parseGbpMicros(
4409
+ quote.grossRevenueFloorMicros,
4410
+ "grossRevenueFloorMicros"
4411
+ );
4412
+ const providerFee = parseGbpMicros(
4413
+ quote.providerFeeMicros,
4414
+ "providerFeeMicros"
4415
+ );
4416
+ const invalidTrafficHaircut = parseGbpMicros(
4417
+ quote.invalidTrafficHaircutMicros,
4418
+ "invalidTrafficHaircutMicros"
4419
+ );
4420
+ const otherCost = parseGbpMicros(quote.otherCostMicros, "otherCostMicros");
4421
+ const eligibleNet = parseGbpMicros(
4422
+ quote.eligibleNetRevenueMicros,
4423
+ "eligibleNetRevenueMicros"
4424
+ );
4425
+ const nominalLiability = parseGbpMicros(
4426
+ quote.nominalLiabilityMicros,
4427
+ "nominalLiabilityMicros"
4428
+ );
4429
+ const retainedMargin = parseGbpMicros(
4430
+ quote.retainedMarginMicros,
4431
+ "retainedMarginMicros"
4432
+ );
4433
+ economyAssert(
4434
+ gross === providerFee + invalidTrafficHaircut + otherCost + eligibleNet,
4435
+ "INVALID_CONTRACT",
4436
+ "Rewarded-web quote revenue arithmetic is inconsistent"
4437
+ );
4438
+ economyAssert(
4439
+ parseTokenSubunits(quote.tokenAmount) === TOKEN_SUBUNITS_PER_TOKEN && nominalLiability === GOOGLE_REWARDED_WEB_NOMINAL_MICROS_PER_TOKEN,
4440
+ "INVALID_CONTRACT",
4441
+ "Rewarded-web quote must issue exactly one whole Token"
4442
+ );
4443
+ economyAssert(
4444
+ eligibleNet >= GOOGLE_REWARDED_WEB_MINIMUM_NET_MICROS_PER_TOKEN && retainedMargin === eligibleNet - nominalLiability && retainedMargin * 5n >= eligibleNet,
4445
+ "INVALID_CONTRACT",
4446
+ "Rewarded-web quote does not preserve the 20% contribution margin"
4447
+ );
4448
+ const effectiveFrom = parseIsoTimestamp(quote.effectiveFrom);
4449
+ if (quote.effectiveUntil !== void 0) {
4450
+ economyAssert(
4451
+ parseIsoTimestamp(quote.effectiveUntil) > effectiveFrom,
4452
+ "INVALID_TIME_WINDOW",
4453
+ "Rewarded-web quote expiry must follow its effective time"
4454
+ );
4455
+ }
4456
+ }
4457
+ function assertGoogleRewardedWebGrantClaim(claim) {
4458
+ assertExactKeys4(
4459
+ claim,
4460
+ /* @__PURE__ */ new Set([
4461
+ "schemaVersion",
4462
+ "provider",
4463
+ "evidenceTrust",
4464
+ "claimId",
4465
+ "sessionId",
4466
+ "beneficiaryAccountId",
4467
+ "quoteVersion",
4468
+ "reportingKeyFingerprint",
4469
+ "rewardPayload",
4470
+ "claimedAt"
4471
+ ]),
4472
+ "Google rewarded-web grant claim"
4473
+ );
4474
+ economyAssert(
4475
+ claim.schemaVersion === ECONOMY_CONTRACT_VERSION && claim.provider === GOOGLE_REWARDED_WEB_PROVIDER && claim.evidenceTrust === "client-claimed",
4476
+ "INVALID_CONTRACT",
4477
+ "Rewarded-web grant evidence must remain client-claimed"
4478
+ );
4479
+ assertEconomyIdentifier(claim.claimId, "claimId");
4480
+ assertEconomyIdentifier(claim.sessionId, "sessionId");
4481
+ assertEconomyIdentifier(claim.beneficiaryAccountId, "beneficiaryAccountId");
4482
+ assertEconomyIdentifier(claim.quoteVersion, "quoteVersion");
4483
+ assertEconomyHmacFingerprint(
4484
+ claim.reportingKeyFingerprint,
4485
+ "economy.google-reporting-key.v1"
4486
+ );
4487
+ assertRewardPayload(claim.rewardPayload);
4488
+ parseIsoTimestamp(claim.claimedAt);
4489
+ }
4490
+ function assertGoogleRewardedWebReconciliation(reconciliation, quote) {
4491
+ assertGoogleRewardedWebQuote(quote);
4492
+ assertExactKeys4(
4493
+ reconciliation,
4494
+ /* @__PURE__ */ new Set([
4495
+ "schemaVersion",
4496
+ "provider",
4497
+ "batchId",
4498
+ "quoteVersion",
4499
+ "state",
4500
+ "reportFinality",
4501
+ "reportFingerprint",
4502
+ "adUnitFingerprint",
4503
+ "periodStartedAt",
4504
+ "periodEndedAt",
4505
+ "acceptedClaimCount",
4506
+ "matchedPaidImpressionCount",
4507
+ "creditedBundleCount",
4508
+ "grossRevenueMicros",
4509
+ "eligibleNetRevenueMicros",
4510
+ "nominalLiabilityMicros",
4511
+ "reserveHeldMicros",
4512
+ "reconciledAt"
4513
+ ]),
4514
+ "Google rewarded-web reconciliation"
4515
+ );
4516
+ economyAssert(
4517
+ reconciliation.schemaVersion === ECONOMY_CONTRACT_VERSION && reconciliation.provider === GOOGLE_REWARDED_WEB_PROVIDER && reconciliation.quoteVersion === quote.quoteVersion && ["report-matched", "financially-reconciled", "mismatch"].includes(
4518
+ reconciliation.state
4519
+ ) && ["estimated", "final"].includes(reconciliation.reportFinality),
4520
+ "INVALID_CONTRACT",
4521
+ "Unsupported Google rewarded-web reconciliation contract"
4522
+ );
4523
+ assertEconomyIdentifier(reconciliation.batchId, "batchId");
4524
+ assertEconomyHmacFingerprint(
4525
+ reconciliation.reportFingerprint,
4526
+ "economy.provider-reconciliation.v1"
4527
+ );
4528
+ economyAssert(
4529
+ SHA256.test(reconciliation.adUnitFingerprint),
4530
+ "INVALID_CONTRACT",
4531
+ "Ad-unit fingerprint must be a canonical SHA-256 reference"
4532
+ );
4533
+ const periodStartedAt = parseIsoTimestamp(reconciliation.periodStartedAt);
4534
+ const periodEndedAt = parseIsoTimestamp(reconciliation.periodEndedAt);
4535
+ const reconciledAt = parseIsoTimestamp(reconciliation.reconciledAt);
4536
+ economyAssert(
4537
+ periodEndedAt > periodStartedAt && reconciledAt >= periodEndedAt,
4538
+ "INVALID_TIME_WINDOW",
4539
+ "Reconciliation period and completion times are inconsistent"
4540
+ );
4541
+ assertBoundedCount(reconciliation.acceptedClaimCount, "acceptedClaimCount");
4542
+ assertBoundedCount(
4543
+ reconciliation.matchedPaidImpressionCount,
4544
+ "matchedPaidImpressionCount"
4545
+ );
4546
+ assertBoundedCount(
4547
+ reconciliation.creditedBundleCount,
4548
+ "creditedBundleCount"
4549
+ );
4550
+ const gross = parseGbpMicros(
4551
+ reconciliation.grossRevenueMicros,
4552
+ "grossRevenueMicros"
4553
+ );
4554
+ const eligibleNet = parseGbpMicros(
4555
+ reconciliation.eligibleNetRevenueMicros,
4556
+ "eligibleNetRevenueMicros"
4557
+ );
4558
+ const nominalLiability = parseGbpMicros(
4559
+ reconciliation.nominalLiabilityMicros,
4560
+ "nominalLiabilityMicros"
4561
+ );
4562
+ const reserveHeld = parseGbpMicros(
4563
+ reconciliation.reserveHeldMicros,
4564
+ "reserveHeldMicros"
4565
+ );
4566
+ const expectedCompletions = BigInt(reconciliation.creditedBundleCount) * BigInt(quote.bundleCompletions);
4567
+ const expectedEligibleNet = BigInt(reconciliation.creditedBundleCount) * BigInt(quote.eligibleNetRevenueMicros);
4568
+ const expectedLiability = BigInt(reconciliation.creditedBundleCount) * BigInt(quote.nominalLiabilityMicros);
4569
+ economyAssert(
4570
+ gross >= eligibleNet && nominalLiability === expectedLiability && reserveHeld >= nominalLiability,
4571
+ "INVALID_CONTRACT",
4572
+ "Reconciliation liability or reserve arithmetic is inconsistent"
4573
+ );
4574
+ if (reconciliation.state === "financially-reconciled") {
4575
+ economyAssert(
4576
+ reconciliation.reportFinality === "final" && BigInt(reconciliation.acceptedClaimCount) >= expectedCompletions && BigInt(reconciliation.matchedPaidImpressionCount) >= expectedCompletions && eligibleNet >= expectedEligibleNet,
4577
+ "INVALID_CONTRACT",
4578
+ "Financial reconciliation requires final paid impressions and revenue coverage"
4579
+ );
4580
+ }
4581
+ }
4582
+ var STATE_TRANSITIONS = {
4583
+ created: /* @__PURE__ */ new Set(["bootstrapped", "suspended", "expired"]),
4584
+ bootstrapped: /* @__PURE__ */ new Set(["client-claimed", "suspended", "expired"]),
4585
+ "client-claimed": /* @__PURE__ */ new Set(["report-matched", "suspended", "expired"]),
4586
+ "report-matched": /* @__PURE__ */ new Set([
4587
+ "financially-reconciled",
4588
+ "suspended",
4589
+ "expired"
4590
+ ]),
4591
+ "financially-reconciled": /* @__PURE__ */ new Set(),
4592
+ suspended: /* @__PURE__ */ new Set(),
4593
+ expired: /* @__PURE__ */ new Set()
4594
+ };
4595
+ function assertGoogleRewardedWebStateTransition(from, to) {
4596
+ economyAssert(
4597
+ STATE_TRANSITIONS[from]?.has(to) === true,
4598
+ "INVALID_CONTRACT",
4599
+ "Rewarded-web session transition is not forward-safe"
4600
+ );
4601
+ }
4602
+
4237
4603
  // src/integrity.ts
4238
4604
  function assertCanonicalHash5(value, label) {
4239
4605
  economyAssert(
@@ -4428,6 +4794,7 @@ function assertSourceLot(lot) {
4428
4794
  "shopify",
4429
4795
  "ayet",
4430
4796
  "bitlabs",
4797
+ "google-ad-manager",
4431
4798
  "subscription",
4432
4799
  "event",
4433
4800
  "competition",
@@ -4450,7 +4817,7 @@ function assertSourceLot(lot) {
4450
4817
  "INVALID_CONTRACT",
4451
4818
  "Source lot has an unsupported refund state"
4452
4819
  );
4453
- if (lot.source === "ayet" || lot.source === "bitlabs") {
4820
+ if (lot.source === "ayet" || lot.source === "bitlabs" || lot.source === "google-ad-manager") {
4454
4821
  economyAssert(
4455
4822
  lot.transferPolicy === "same-user-only" && lot.providerEventId !== void 0,
4456
4823
  "SOURCE_LOT_RESTRICTED",
@@ -5544,7 +5911,7 @@ var DECISIONS = /* @__PURE__ */ new Set([
5544
5911
  "approve",
5545
5912
  "reject"
5546
5913
  ]);
5547
- function assertExactKeys4(value, allowed, label) {
5914
+ function assertExactKeys5(value, allowed, label) {
5548
5915
  economyAssert(
5549
5916
  value !== null && typeof value === "object" && !Array.isArray(value),
5550
5917
  "INVALID_CONTRACT",
@@ -5571,7 +5938,7 @@ function assertReasonCode(reasonCode) {
5571
5938
  );
5572
5939
  }
5573
5940
  function assertOperatorAdjustmentPreview(preview) {
5574
- assertExactKeys4(preview, PREVIEW_KEYS, "Operator adjustment preview");
5941
+ assertExactKeys5(preview, PREVIEW_KEYS, "Operator adjustment preview");
5575
5942
  economyAssert(
5576
5943
  preview.schemaVersion === ECONOMY_CONTRACT_VERSION && OPERATIONS.has(preview.operation) && TARGET_COMPONENTS.has(preview.targetComponent) && TRANSFER_POLICIES.has(preview.transferPolicy) && preview.refundPolicy === "not-refundable",
5577
5944
  "INVALID_CONTRACT",
@@ -5650,7 +6017,7 @@ function canonicalOperatorAdjustmentPreviewPayload(preview) {
5650
6017
  function assertOperatorAdjustmentProposal(proposal, preview, expectedPreviewHash) {
5651
6018
  assertOperatorAdjustmentPreview(preview);
5652
6019
  assertCanonicalHash6(expectedPreviewHash, "expectedPreviewHash");
5653
- assertExactKeys4(proposal, PROPOSAL_KEYS, "Operator adjustment proposal");
6020
+ assertExactKeys5(proposal, PROPOSAL_KEYS, "Operator adjustment proposal");
5654
6021
  economyAssert(
5655
6022
  proposal.schemaVersion === ECONOMY_CONTRACT_VERSION && proposal.status === "pending-approval",
5656
6023
  "INVALID_CONTRACT",
@@ -5677,7 +6044,7 @@ function assertOperatorAdjustmentProposal(proposal, preview, expectedPreviewHash
5677
6044
  );
5678
6045
  }
5679
6046
  function canonicalOperatorAdjustmentProposalPayload(proposal) {
5680
- assertExactKeys4(proposal, PROPOSAL_KEYS, "Operator adjustment proposal");
6047
+ assertExactKeys5(proposal, PROPOSAL_KEYS, "Operator adjustment proposal");
5681
6048
  return JSON.stringify({
5682
6049
  schemaVersion: proposal.schemaVersion,
5683
6050
  proposalId: proposal.proposalId,
@@ -5692,7 +6059,7 @@ function canonicalOperatorAdjustmentProposalPayload(proposal) {
5692
6059
  function assertOperatorAdjustmentDecision(decision, proposal, preview, expectedPreviewHash, expectedProposalHash) {
5693
6060
  assertOperatorAdjustmentProposal(proposal, preview, expectedPreviewHash);
5694
6061
  assertCanonicalHash6(expectedProposalHash, "expectedProposalHash");
5695
- assertExactKeys4(decision, DECISION_KEYS, "Operator adjustment decision");
6062
+ assertExactKeys5(decision, DECISION_KEYS, "Operator adjustment decision");
5696
6063
  economyAssert(
5697
6064
  decision.schemaVersion === ECONOMY_CONTRACT_VERSION && DECISIONS.has(decision.decision),
5698
6065
  "INVALID_CONTRACT",
@@ -5735,7 +6102,7 @@ function assertOperatorAdjustmentDecision(decision, proposal, preview, expectedP
5735
6102
  );
5736
6103
  }
5737
6104
  function canonicalOperatorAdjustmentDecisionPayload(decision) {
5738
- assertExactKeys4(decision, DECISION_KEYS, "Operator adjustment decision");
6105
+ assertExactKeys5(decision, DECISION_KEYS, "Operator adjustment decision");
5739
6106
  return JSON.stringify({
5740
6107
  schemaVersion: decision.schemaVersion,
5741
6108
  decisionId: decision.decisionId,
@@ -5759,7 +6126,7 @@ function assertOperatorAdjustmentExecution(execution, preview, proposal, decisio
5759
6126
  expectedProposalHash
5760
6127
  );
5761
6128
  assertCanonicalHash6(expectedDecisionHash, "expectedDecisionHash");
5762
- assertExactKeys4(execution, EXECUTION_KEYS, "Operator adjustment execution");
6129
+ assertExactKeys5(execution, EXECUTION_KEYS, "Operator adjustment execution");
5763
6130
  economyAssert(
5764
6131
  execution.schemaVersion === ECONOMY_CONTRACT_VERSION,
5765
6132
  "INVALID_CONTRACT",
@@ -5790,7 +6157,7 @@ function assertOperatorAdjustmentExecution(execution, preview, proposal, decisio
5790
6157
  );
5791
6158
  }
5792
6159
  function canonicalOperatorAdjustmentExecutionPayload(execution) {
5793
- assertExactKeys4(execution, EXECUTION_KEYS, "Operator adjustment execution");
6160
+ assertExactKeys5(execution, EXECUTION_KEYS, "Operator adjustment execution");
5794
6161
  return JSON.stringify({
5795
6162
  schemaVersion: execution.schemaVersion,
5796
6163
  executionId: execution.executionId,
@@ -6863,6 +7230,7 @@ var ACTIVITY_SOURCES3 = /* @__PURE__ */ new Set([
6863
7230
  "shopify",
6864
7231
  "ayet",
6865
7232
  "bitlabs",
7233
+ "google-ad-manager",
6866
7234
  "subscription",
6867
7235
  "event",
6868
7236
  "competition",
@@ -8345,7 +8713,7 @@ var PORTABLE_KEYS = /* @__PURE__ */ new Set([
8345
8713
  "signature",
8346
8714
  ...PORTABLE_BODY_KEYS
8347
8715
  ]);
8348
- function assertExactKeys5(value, allowedKeys, label) {
8716
+ function assertExactKeys6(value, allowedKeys, label) {
8349
8717
  economyAssert(
8350
8718
  value !== null && typeof value === "object" && !Array.isArray(value),
8351
8719
  "INVALID_CONTRACT",
@@ -8434,7 +8802,7 @@ function canonicalSignatureMetadata(signature) {
8434
8802
  };
8435
8803
  }
8436
8804
  function assertEconomySealedRecoveryPayload(payload) {
8437
- assertExactKeys5(
8805
+ assertExactKeys6(
8438
8806
  payload,
8439
8807
  /* @__PURE__ */ new Set([
8440
8808
  "schemaVersion",
@@ -8474,7 +8842,7 @@ function assertEconomySealedRecoveryPayload(payload) {
8474
8842
  );
8475
8843
  }
8476
8844
  function assertAcceptanceBody(body) {
8477
- assertExactKeys5(
8845
+ assertExactKeys6(
8478
8846
  body,
8479
8847
  "acceptanceEnvelopeId" in body ? ACCEPTANCE_KEYS : ACCEPTANCE_BODY_KEYS,
8480
8848
  "Recovery acceptance body"
@@ -8543,7 +8911,7 @@ function createEconomyRecoveryAcceptanceEnvelope(body, hashCanonicalPayload2) {
8543
8911
  };
8544
8912
  }
8545
8913
  function assertEconomyRecoveryAcceptanceEnvelope(envelope, hashCanonicalPayload2) {
8546
- assertExactKeys5(envelope, ACCEPTANCE_KEYS, "Recovery acceptance envelope");
8914
+ assertExactKeys6(envelope, ACCEPTANCE_KEYS, "Recovery acceptance envelope");
8547
8915
  assertAcceptanceBody(envelope);
8548
8916
  assertEconomyIdentifier(
8549
8917
  envelope.acceptanceEnvelopeId,
@@ -8584,7 +8952,7 @@ function canonicalEconomyRecoveryAcceptanceEnvelopePayload(envelope, hashCanonic
8584
8952
  });
8585
8953
  }
8586
8954
  function assertCommittedResultBody(body) {
8587
- assertExactKeys5(
8955
+ assertExactKeys6(
8588
8956
  body,
8589
8957
  "committedResultId" in body ? COMMITTED_RESULT_KEYS : COMMITTED_RESULT_BODY_KEYS,
8590
8958
  "Recovery committed-result body"
@@ -8678,7 +9046,7 @@ function createEconomyRecoveryCommittedResult(body, hashCanonicalPayload2) {
8678
9046
  };
8679
9047
  }
8680
9048
  function assertEconomyRecoveryCommittedResult(result, hashCanonicalPayload2) {
8681
- assertExactKeys5(
9049
+ assertExactKeys6(
8682
9050
  result,
8683
9051
  COMMITTED_RESULT_KEYS,
8684
9052
  "Recovery committed result"
@@ -8737,7 +9105,7 @@ function assertEconomyRecoveryResultLink(acceptance, result, hashCanonicalPayloa
8737
9105
  );
8738
9106
  }
8739
9107
  function assertEconomyEvidenceSignatureMetadata(signature) {
8740
- assertExactKeys5(
9108
+ assertExactKeys6(
8741
9109
  signature,
8742
9110
  /* @__PURE__ */ new Set([
8743
9111
  "schemaVersion",
@@ -8757,7 +9125,7 @@ function assertEconomyEvidenceSignatureMetadata(signature) {
8757
9125
  parseIsoTimestamp(signature.signedAt);
8758
9126
  }
8759
9127
  function assertEconomyEvidenceSignature(signature) {
8760
- assertExactKeys5(
9128
+ assertExactKeys6(
8761
9129
  signature,
8762
9130
  /* @__PURE__ */ new Set([
8763
9131
  "schemaVersion",
@@ -8779,7 +9147,7 @@ function assertEconomyEvidenceSignature(signature) {
8779
9147
  assertBase64url(signature.value, "Evidence signature value", 32, 2048);
8780
9148
  }
8781
9149
  function assertRegionalEvidenceBody(body) {
8782
- assertExactKeys5(
9150
+ assertExactKeys6(
8783
9151
  body,
8784
9152
  "evidenceReceiptId" in body ? REGIONAL_KEYS : REGIONAL_BODY_KEYS,
8785
9153
  "Regional evidence-receipt body"
@@ -8871,7 +9239,7 @@ function createEconomyRegionalEvidenceReceipt(body, signature, hashCanonicalPayl
8871
9239
  };
8872
9240
  }
8873
9241
  function assertEconomyRegionalEvidenceReceipt(receipt, hashCanonicalPayload2) {
8874
- assertExactKeys5(receipt, REGIONAL_KEYS, "Regional evidence receipt");
9242
+ assertExactKeys6(receipt, REGIONAL_KEYS, "Regional evidence receipt");
8875
9243
  assertRegionalEvidenceBody(receipt);
8876
9244
  assertEconomyIdentifier(receipt.evidenceReceiptId, "evidenceReceiptId");
8877
9245
  assertEconomyEvidenceSignature(receipt.signature);
@@ -9073,7 +9441,7 @@ function assertEconomyRegionalEvidenceEquality(receipts, expectedRegions, hashCa
9073
9441
  );
9074
9442
  }
9075
9443
  function assertEconomyMerkleInclusionProof(proof) {
9076
- assertExactKeys5(
9444
+ assertExactKeys6(
9077
9445
  proof,
9078
9446
  /* @__PURE__ */ new Set([
9079
9447
  "schemaVersion",
@@ -9104,7 +9472,7 @@ function assertEconomyMerkleInclusionProof(proof) {
9104
9472
  "Merkle leaf position is outside its bounded tree"
9105
9473
  );
9106
9474
  for (const step of proof.siblings) {
9107
- assertExactKeys5(
9475
+ assertExactKeys6(
9108
9476
  step,
9109
9477
  /* @__PURE__ */ new Set(["schemaVersion", "side", "hash"]),
9110
9478
  "Merkle proof step"
@@ -9193,7 +9561,7 @@ function assertEconomyMerkleInclusion(proof, anchor, hashCanonicalPayload2) {
9193
9561
  );
9194
9562
  }
9195
9563
  function assertPortableEvidenceReference(reference) {
9196
- assertExactKeys5(
9564
+ assertExactKeys6(
9197
9565
  reference,
9198
9566
  /* @__PURE__ */ new Set([
9199
9567
  "schemaVersion",
@@ -9230,7 +9598,7 @@ function canonicalPortableEvidenceReference(reference) {
9230
9598
  };
9231
9599
  }
9232
9600
  function assertPortableBody(body) {
9233
- assertExactKeys5(
9601
+ assertExactKeys6(
9234
9602
  body,
9235
9603
  "portableReceiptId" in body ? PORTABLE_KEYS : PORTABLE_BODY_KEYS,
9236
9604
  "Portable customer-receipt body"
@@ -9354,7 +9722,7 @@ function createEconomyPortableCustomerReceipt(body, signature, hashCanonicalPayl
9354
9722
  };
9355
9723
  }
9356
9724
  function assertEconomyPortableCustomerReceipt(receipt, hashCanonicalPayload2) {
9357
- assertExactKeys5(receipt, PORTABLE_KEYS, "Portable customer receipt");
9725
+ assertExactKeys6(receipt, PORTABLE_KEYS, "Portable customer receipt");
9358
9726
  assertPortableBody(receipt);
9359
9727
  assertEconomyIdentifier(receipt.portableReceiptId, "portableReceiptId");
9360
9728
  assertEconomyEvidenceSignature(receipt.signature);
@@ -9654,7 +10022,7 @@ var DOCUMENT_ID_KEYS = /* @__PURE__ */ new Set([
9654
10022
  "lifetimeProjectionId",
9655
10023
  "outboxEventId"
9656
10024
  ]);
9657
- function assertExactKeys6(value, allowed, label) {
10025
+ function assertExactKeys7(value, allowed, label) {
9658
10026
  economyAssert(
9659
10027
  value !== null && typeof value === "object" && !Array.isArray(value),
9660
10028
  "INVALID_CONTRACT",
@@ -9694,7 +10062,7 @@ function createPersonalWalletInitializationDocumentIds(subjectAccountId, hash) {
9694
10062
  };
9695
10063
  }
9696
10064
  function assertPersonalWalletInitializationCommand(command) {
9697
- assertExactKeys6(command, COMMAND_KEYS, "Wallet initialization command");
10065
+ assertExactKeys7(command, COMMAND_KEYS, "Wallet initialization command");
9698
10066
  economyAssert(
9699
10067
  command.schemaVersion === ECONOMY_CONTRACT_VERSION && command.commandType === "initialize-wallet" && command.walletKind === "personal",
9700
10068
  "INVALID_CONTRACT",
@@ -9718,7 +10086,7 @@ function canonicalPersonalWalletInitializationCommandPayload(command) {
9718
10086
  });
9719
10087
  }
9720
10088
  function assertPersonalWalletInitializationOutboxIntent(intent) {
9721
- assertExactKeys6(intent, OUTBOX_KEYS, "Wallet initialization outbox intent");
10089
+ assertExactKeys7(intent, OUTBOX_KEYS, "Wallet initialization outbox intent");
9722
10090
  economyAssert(
9723
10091
  intent.schemaVersion === ECONOMY_CONTRACT_VERSION && intent.eventType === "wallet.initialized.v1",
9724
10092
  "INVALID_CONTRACT",
@@ -9818,8 +10186,8 @@ function createPersonalWalletInitializationState(input, hash) {
9818
10186
  return state;
9819
10187
  }
9820
10188
  function assertPersonalWalletInitializationState(state) {
9821
- assertExactKeys6(state, STATE_KEYS, "Wallet initialization state");
9822
- assertExactKeys6(
10189
+ assertExactKeys7(state, STATE_KEYS, "Wallet initialization state");
10190
+ assertExactKeys7(
9823
10191
  state.documentIds,
9824
10192
  DOCUMENT_ID_KEYS,
9825
10193
  "Wallet initialization document IDs"
@@ -9870,6 +10238,9 @@ export {
9870
10238
  ECONOMY_CONTRACT_VERSION,
9871
10239
  ECONOMY_RECOVERY_PROTOCOL_VERSION,
9872
10240
  EconomyError,
10241
+ GOOGLE_REWARDED_WEB_MINIMUM_NET_MICROS_PER_TOKEN,
10242
+ GOOGLE_REWARDED_WEB_NOMINAL_MICROS_PER_TOKEN,
10243
+ GOOGLE_REWARDED_WEB_PROVIDER,
9873
10244
  MODULE_ALLOWANCE_PURPOSE,
9874
10245
  PRE_UTILITY_BACKER_COHORT,
9875
10246
  TOKEN_SUBUNITS_MAX,
@@ -9942,6 +10313,10 @@ export {
9942
10313
  assertFlatTokenCatalog,
9943
10314
  assertFxSnapshot,
9944
10315
  assertGameplayAllocation,
10316
+ assertGoogleRewardedWebGrantClaim,
10317
+ assertGoogleRewardedWebQuote,
10318
+ assertGoogleRewardedWebReconciliation,
10319
+ assertGoogleRewardedWebStateTransition,
9945
10320
  assertJournalChainHead,
9946
10321
  assertModuleAllowance,
9947
10322
  assertModulePurchaseReceipt,
@@ -10035,6 +10410,7 @@ export {
10035
10410
  createEconomyRecoveryCommittedResult,
10036
10411
  createEconomyRegionalEvidenceReceipt,
10037
10412
  createGameplayAllocation,
10413
+ createGoogleRewardedWebQuote,
10038
10414
  createInitialSourceLotSnapshot,
10039
10415
  createModuleAllowance,
10040
10416
  createModulePurchaseReceipt,