@plasius/economy 0.10.0 → 0.11.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.
package/README.md CHANGED
@@ -85,6 +85,13 @@ not raise these defaults without a separately versioned policy decision.
85
85
  `GoogleRewardedWebReconciliationV1` separately proves final paid-impression,
86
86
  eligible-net-revenue, nominal-liability, and reserve coverage.
87
87
 
88
+ The audited authority treats `google-ad-manager` as a provider command source.
89
+ Final reports use `authenticated-retrieval` evidence with a bounded retrieval
90
+ scheme and verification time; they cannot be represented as signed callbacks.
91
+ Legacy Shopify, ayeT, and BitLabs signed-evidence canonical bytes remain
92
+ unchanged. Google reward credits consequently require the provider-acceptance
93
+ and provider-result authority boundaries and produce `rewarded-ad` activity.
94
+
88
95
  `createGoogleRewardedWebQuote()` uses exact integer GBP micros and issues one
89
96
  whole Token only when conservative eligible net is at least 125,000 micros for
90
97
  the 100,000-micro nominal liability. The completion bundle has no package
@@ -576,12 +583,12 @@ Coverage must remain at least 80%, and every changed source file must appear in
576
583
  LCOV. Generated property tests cover exact arithmetic, double-entry balance,
577
584
  projection rebuilds, idempotency, reversals, lot isolation, and allocation
578
585
  non-negativity. npm publication is performed only by the approved GitHub CD
579
- workflow on configurable trusted self-hosted runners. Release LCOV and the
580
- CycloneDX SBOM remain retained even when an external coverage or npm provenance
581
- service is unavailable. Release tags and GitHub Releases use a current-repository
582
- GitHub App token with explicit Contents and Workflows write permissions; npm
583
- publication continues to use only the protected `NPM_TOKEN`. Both release jobs
584
- install a checksum-pinned GitHub CLI under `RUNNER_TEMP`. A requested version
586
+ workflow from the protected `main` branch. The final publication job runs on a
587
+ GitHub-hosted runner so npm can validate its short-lived OIDC identity and
588
+ record provenance; it has no long-lived npm write-token fallback. Release LCOV
589
+ and the CycloneDX SBOM remain retained even when an external coverage service
590
+ is unavailable. Release tags and GitHub Releases use a current-repository
591
+ GitHub App token with explicit Contents and Workflows write permissions. A requested version
585
592
  bump reuses the current version only when neither npm nor GitHub records it as a
586
593
  completed release; use `bump=none` for deliberate recovery of prepared metadata.
587
594
  Publication checks out the verified current release-branch HEAD so that recovery
@@ -593,3 +600,16 @@ Do not include raw idempotency keys, provider identifiers, provider callback
593
600
  bodies or signatures, payment details, personal data, encrypted-handle
594
601
  ciphertext, or secrets in contracts, metadata, tests, examples, or logs.
595
602
  Report vulnerabilities privately according to [SECURITY.md](./SECURITY.md).
603
+ <!-- BEGIN PLASIUS RELEASE INTEGRITY -->
604
+ ## Release integrity
605
+
606
+ Production package publication runs only from `.github/workflows/cd.yml` on
607
+ protected `main`. The job verifies that the prepared commit is still the
608
+ current main commit and has an exact successful `ci.yml` push result before it
609
+ mutates release state. Public package CI runs on GitHub-hosted capacity so it
610
+ cannot execute on company-managed runners. npm publication runs on
611
+ GitHub-hosted Node.js 24 with
612
+ npm 11.5.1 or newer, uses the protected `production` environment and
613
+ short-lived npm OIDC with provenance, and has no long-lived npm write-token
614
+ fallback. Rollback disables CD; it never rewrites published package history.
615
+ <!-- END PLASIUS RELEASE INTEGRITY -->
package/dist/index.cjs CHANGED
@@ -2169,6 +2169,7 @@ var COMMAND_SOURCES = /* @__PURE__ */ new Set([
2169
2169
  "shopify",
2170
2170
  "ayet",
2171
2171
  "bitlabs",
2172
+ "google-ad-manager",
2172
2173
  "operator",
2173
2174
  "system"
2174
2175
  ]);
@@ -2181,7 +2182,8 @@ var PRINCIPAL_TYPES = /* @__PURE__ */ new Set([
2181
2182
  var PROVIDER_SOURCES = /* @__PURE__ */ new Set([
2182
2183
  "shopify",
2183
2184
  "ayet",
2184
- "bitlabs"
2185
+ "bitlabs",
2186
+ "google-ad-manager"
2185
2187
  ]);
2186
2188
  var CAUSATION_KINDS = /* @__PURE__ */ new Set([
2187
2189
  "provider-event",
@@ -2193,7 +2195,8 @@ var CAUSATION_KINDS = /* @__PURE__ */ new Set([
2193
2195
  var PROVIDERS = /* @__PURE__ */ new Set([
2194
2196
  "shopify",
2195
2197
  "ayet",
2196
- "bitlabs"
2198
+ "bitlabs",
2199
+ "google-ad-manager"
2197
2200
  ]);
2198
2201
  var FINGERPRINT_DOMAINS = /* @__PURE__ */ new Set([
2199
2202
  "economy.idempotency-key.v1",
@@ -2223,6 +2226,12 @@ var SOURCE_COMMAND_TYPES = {
2223
2226
  ]),
2224
2227
  ayet: /* @__PURE__ */ new Set(["credit-reward", "hold", "release-hold", "reverse"]),
2225
2228
  bitlabs: /* @__PURE__ */ new Set(["credit-reward", "hold", "release-hold", "reverse"]),
2229
+ "google-ad-manager": /* @__PURE__ */ new Set([
2230
+ "credit-reward",
2231
+ "hold",
2232
+ "release-hold",
2233
+ "reverse"
2234
+ ]),
2226
2235
  operator: /* @__PURE__ */ new Set(["adjust", "reverse", "hold", "release-hold"]),
2227
2236
  system: /* @__PURE__ */ new Set([
2228
2237
  "credit-event",
@@ -2496,6 +2505,9 @@ function assertEconomyProviderEvidenceHash(evidence) {
2496
2505
  "reconciliationEvidenceFingerprint",
2497
2506
  "signatureScheme",
2498
2507
  "signatureVerifiedAt",
2508
+ "verificationMode",
2509
+ "authenticatedRetrievalScheme",
2510
+ "authenticatedRetrievedAt",
2499
2511
  "providerOccurredAt",
2500
2512
  "receivedAt",
2501
2513
  "operationalHandleBindingId"
@@ -2530,9 +2542,27 @@ function assertEconomyProviderEvidenceHash(evidence) {
2530
2542
  );
2531
2543
  }
2532
2544
  assertSafeClassifier(evidence.eventType, "Provider event type");
2533
- assertSafeClassifier(evidence.signatureScheme, "Provider signature scheme");
2534
- const signatureVerifiedAt = parseIsoTimestamp(evidence.signatureVerifiedAt);
2535
2545
  const receivedAt = parseIsoTimestamp(evidence.receivedAt);
2546
+ const signatureFieldsPresent = evidence.signatureScheme !== void 0 && evidence.signatureVerifiedAt !== void 0;
2547
+ const retrievalFieldsPresent = evidence.authenticatedRetrievalScheme !== void 0 && evidence.authenticatedRetrievedAt !== void 0;
2548
+ const verificationMode = evidence.verificationMode ?? "provider-signature";
2549
+ economyAssert(
2550
+ 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,
2551
+ "INVALID_CONTRACT",
2552
+ "Provider evidence must use exactly one permitted verification method"
2553
+ );
2554
+ const verifiedAt = verificationMode === "provider-signature" ? evidence.signatureVerifiedAt : evidence.authenticatedRetrievedAt;
2555
+ if (verificationMode === "provider-signature") {
2556
+ assertSafeClassifier(
2557
+ evidence.signatureScheme,
2558
+ "Provider signature scheme"
2559
+ );
2560
+ } else {
2561
+ assertSafeClassifier(
2562
+ evidence.authenticatedRetrievalScheme,
2563
+ "Provider authenticated-retrieval scheme"
2564
+ );
2565
+ }
2536
2566
  if (evidence.providerOccurredAt !== void 0) {
2537
2567
  economyAssert(
2538
2568
  parseIsoTimestamp(evidence.providerOccurredAt) <= receivedAt,
@@ -2541,9 +2571,9 @@ function assertEconomyProviderEvidenceHash(evidence) {
2541
2571
  );
2542
2572
  }
2543
2573
  economyAssert(
2544
- receivedAt >= signatureVerifiedAt,
2574
+ receivedAt >= parseIsoTimestamp(verifiedAt),
2545
2575
  "INVALID_TIME_WINDOW",
2546
- "Provider evidence cannot be received before signature verification"
2576
+ "Provider evidence cannot be received before verification"
2547
2577
  );
2548
2578
  if (evidence.operationalHandleBindingId !== void 0) {
2549
2579
  assertEconomyIdentifier(
@@ -2893,8 +2923,13 @@ function canonicalEconomyProviderEvidenceHashPayload(evidence) {
2893
2923
  evidence.reconciliationEvidenceFingerprint
2894
2924
  )
2895
2925
  },
2896
- signatureScheme: evidence.signatureScheme,
2897
- signatureVerifiedAt: evidence.signatureVerifiedAt,
2926
+ ...evidence.verificationMode === void 0 ? {} : { verificationMode: evidence.verificationMode },
2927
+ ...evidence.signatureScheme === void 0 ? {} : { signatureScheme: evidence.signatureScheme },
2928
+ ...evidence.signatureVerifiedAt === void 0 ? {} : { signatureVerifiedAt: evidence.signatureVerifiedAt },
2929
+ ...evidence.authenticatedRetrievalScheme === void 0 ? {} : {
2930
+ authenticatedRetrievalScheme: evidence.authenticatedRetrievalScheme
2931
+ },
2932
+ ...evidence.authenticatedRetrievedAt === void 0 ? {} : { authenticatedRetrievedAt: evidence.authenticatedRetrievedAt },
2898
2933
  ...evidence.providerOccurredAt === void 0 ? {} : { providerOccurredAt: evidence.providerOccurredAt },
2899
2934
  receivedAt: evidence.receivedAt,
2900
2935
  ...evidence.operationalHandleBindingId === void 0 ? {} : {
@@ -3948,6 +3983,15 @@ function assertReversalAvailable(originalTransactionId, existingTransactions) {
3948
3983
  }
3949
3984
 
3950
3985
  // src/audit-graph.ts
3986
+ var PROVIDER_COMMAND_SOURCES = /* @__PURE__ */ new Set([
3987
+ "shopify",
3988
+ "ayet",
3989
+ "bitlabs",
3990
+ "google-ad-manager"
3991
+ ]);
3992
+ function isProviderCommandSource(source) {
3993
+ return PROVIDER_COMMAND_SOURCES.has(source);
3994
+ }
3951
3995
  function assertCanonicalHash4(value, label) {
3952
3996
  economyAssert(
3953
3997
  typeof value === "string" && /^sha256:[a-f0-9]{64}$/u.test(value),
@@ -3975,7 +4019,7 @@ function assertCreatedReference(manifest, kind, id, contentHash) {
3975
4019
  }
3976
4020
  function assertProviderGraph(graph, hash, acceptanceCommit) {
3977
4021
  const envelope = graph.commandEnvelope;
3978
- const providerSource = envelope.commandSource === "shopify" || envelope.commandSource === "ayet" || envelope.commandSource === "bitlabs";
4022
+ const providerSource = isProviderCommandSource(envelope.commandSource);
3979
4023
  if (!providerSource) {
3980
4024
  economyAssert(
3981
4025
  graph.providerEvidenceManifest === void 0 && graph.providerEvidence.length === 0 && graph.operationalHandleBindings.length === 0,
@@ -4122,7 +4166,7 @@ function expectedTransactionActivityTypes(envelope) {
4122
4166
  }
4123
4167
  if (envelope.commandType === "credit-reward") {
4124
4168
  return /* @__PURE__ */ new Set([
4125
- envelope.commandSource === "ayet" ? "rewarded-ad" : "offerwall"
4169
+ envelope.commandSource === "ayet" || envelope.commandSource === "google-ad-manager" ? "rewarded-ad" : "offerwall"
4126
4170
  ]);
4127
4171
  }
4128
4172
  if (envelope.commandType === "credit-event") {
@@ -4177,7 +4221,7 @@ function assertReceiptGraph(graph, commandEnvelopeHash, hash, acceptanceCommit,
4177
4221
  accepted.receiptId,
4178
4222
  acceptedHash
4179
4223
  );
4180
- const providerSource = envelope.commandSource === "shopify" || envelope.commandSource === "ayet" || envelope.commandSource === "bitlabs";
4224
+ const providerSource = isProviderCommandSource(envelope.commandSource);
4181
4225
  if (graph.resultReceipt === void 0) {
4182
4226
  economyAssert(
4183
4227
  providerSource && graph.transaction === void 0 && resultCommit === void 0,
@@ -4297,7 +4341,9 @@ function assertAuthorityCommits(graph, hash) {
4297
4341
  "INVALID_CONTRACT",
4298
4342
  "Authority commits do not reconstruct the expected authority head"
4299
4343
  );
4300
- const providerSource = graph.commandEnvelope.commandSource === "shopify" || graph.commandEnvelope.commandSource === "ayet" || graph.commandEnvelope.commandSource === "bitlabs";
4344
+ const providerSource = isProviderCommandSource(
4345
+ graph.commandEnvelope.commandSource
4346
+ );
4301
4347
  const acceptanceKind = providerSource ? "provider-acceptance" : "first-party-command";
4302
4348
  const acceptanceCommit = graph.commits.find(
4303
4349
  (commit) => commit.manifest.commitKind === acceptanceKind