@plasius/economy 0.2.0 → 0.3.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
@@ -53,6 +53,13 @@ reject non-string JSON values rather than coercing numbers into wire amounts.
53
53
  display-oriented `sourceLabel`. Filters and reconciliation must use `source`;
54
54
  localized UI must use `sourceLabel`.
55
55
 
56
+ New read adapters should return the discriminated `WalletActivityEntryV1`.
57
+ `economic` rows may be `held`, `settled`, or read-model-derived `reversed`;
58
+ `workflow` rows alone may be `pending` or `failed`. The additive
59
+ `EconomicJournalTransactionV1` narrows immutable journal writes to `held` or
60
+ `settled`. A reversed display state is derived from a compensating transaction;
61
+ the original journal row is never rewritten.
62
+
56
63
  ## Baseline GBP catalog
57
64
 
58
65
  `BASELINE_GBP_REFERENCE_RATE` is versioned product-copy metadata with
@@ -113,7 +120,11 @@ const payloadForApprovedHashAdapter = canonicalTransactionPayload(transaction);
113
120
  ```
114
121
 
115
122
  The package produces canonical bytes but deliberately leaves SHA-256/HSM
116
- signing to an approved infrastructure adapter.
123
+ signing to an approved infrastructure adapter. Metadata keys and posting IDs
124
+ are ordered with locale-independent UTF-16 code-unit comparison. Their
125
+ validated ASCII alphabet makes that ordering identical to PostgreSQL
126
+ `COLLATE "C"`; adapters must hash the exact UTF-8 bytes returned by
127
+ `canonicalTransactionPayload()`.
117
128
 
118
129
  ## Source-lot policy and allocations
119
130
 
@@ -128,12 +139,27 @@ the source rows, revalidate them, append the balanced transaction, update the
128
139
  projection, save idempotency evidence, and append the outbox event within one
129
140
  serializable database transaction.
130
141
 
142
+ `VersionedSourceLotV1` and `SourceLotMovementV1` make allocation, boost,
143
+ reclaim, spend, hold, release, refund, chargeback, and reversal changes explicit.
144
+ `applySourceLotMovement()` proves the signed amount deltas, refund-state
145
+ transition, and exact optimistic-version increment. A V2 persistence adapter
146
+ must append the movement evidence and compare-and-swap the projection as one
147
+ operation.
148
+
131
149
  ## Early backers
132
150
 
133
151
  `evaluateEarlyBacker()` calculates provisional `pre_utility_backer_v1` status
134
152
  from net retained paid lots. It uses an inclusive public launch and exclusive
135
153
  first-public-spend cutoff. It does not express or promise a reward entitlement.
136
154
 
155
+ Existing `evaluateEarlyBacker()` behavior is preserved for V1 consumers. The
156
+ approved additive `evaluateEarlyBackerBySettlementV2()` policy treats
157
+ `settledAt` as the sole inclusive-launch/exclusive-cutoff qualification event;
158
+ purchase and credit timestamps remain ordering/provenance facts. It ignores
159
+ settlements after `evaluatedAt`. The caller must derive both window timestamps
160
+ from the entire public cohort and exclude non-production/test lots: staff,
161
+ closed-beta, and test availability must never open or close the public window.
162
+
137
163
  ## Acquisition and future contracts
138
164
 
139
165
  Purchase intents bind payer, receiving household/wallet, pack, catalog,
@@ -150,15 +176,54 @@ to household-allocatable is rejected.
150
176
  monthly/100 Token shape with `enabled: false`. Spend-request contracts likewise
151
177
  exist for future use but this package does not enable their creation.
152
178
 
179
+ ## Balance, lifetime, and portfolio reads
180
+
181
+ `WalletBalanceProjectionV1` stores exclusive `spendable`, `reserved`, and
182
+ `held` buckets. `createWalletBalanceSummary()` splits each wallet's spendable
183
+ amount into independently usable whole-Token `available` value and a
184
+ sub-Token `rewardProgress` remainder. `WalletBalanceDeltaV1` is an atomic add,
185
+ never an absolute balance replacement.
186
+
187
+ Lifetime counters are monotonic gross flows. Settled purchase/subscription
188
+ credits add to `bought`; rewarded-ad, offerwall, event, and competition credits
189
+ add to `earned`; source-wallet allocation/boost debits add to `allocated`;
190
+ returns add to `reclaimed`; spend debits add to `spent`; and refund,
191
+ chargeback, or reversal debits add to `reversed`. A reversal does not subtract
192
+ from the earlier bought/earned counter.
193
+
194
+ `EconomyQueryPortV1` keeps single-wallet reads and introduces an explicit
195
+ `WalletPortfolioReadScopeV1`. A host portfolio may contain both a household
196
+ treasury and a same-user-only personal reward wallet, and every component keeps
197
+ its wallet ID, role, beneficiary, summary, and lifetime snapshot. Portfolio
198
+ totals are display-only column sums: progress is deliberately not promoted
199
+ across wallets, even if the sum reaches 1,000 TokenSubunits, because source and
200
+ transfer restrictions may differ. Authorization must happen before the server
201
+ constructs a portfolio scope.
202
+
203
+ Activity reads use bounded opaque cursor pagination in stable descending
204
+ `(occurredAt, activityId)` order. Each row retains the component `walletId`
205
+ whose signed display amount it represents. Cursor contents and signatures are
206
+ adapter concerns; `assertWalletActivityPageForPortfolio()` proves that a result
207
+ never expands the authorized portfolio scope.
208
+
153
209
  ## Persistence ports
154
210
 
155
- Implement `EconomyPersistencePort` in the authoritative service. Runtime roles
156
- should execute approved posting procedures but must not update or delete journal
157
- rows directly. The adapter is responsible for:
211
+ `EconomyPersistencePort` remains exported unchanged for existing consumers.
212
+ New authoritative services should implement `EconomyPersistencePortV2`, whose
213
+ unit of work deliberately omits V1's whole-projection overwrite. Runtime roles
214
+ should execute approved posting procedures but must not update or delete
215
+ journal rows directly. The V2 adapter is responsible for:
158
216
 
159
217
  - serializable row locking and optimistic versions;
160
- - unique transaction, idempotency, and provider-event constraints;
161
- - same-transaction projection and source-lot updates;
218
+ - exact owner-constrained wallet access and household/child-constrained
219
+ allocation compare-and-swap;
220
+ - immutable accepted-command and workflow-event append;
221
+ - actor/subject/command-scoped idempotency plus unique transaction and
222
+ provider-event constraints;
223
+ - active regional writer-fence validation and locked canonical chain-head
224
+ extension;
225
+ - atomic wallet balance and monotonic lifetime deltas;
226
+ - atomic source-lot movement append, refund-state update, and version advance;
162
227
  - transactional outbox append;
163
228
  - managed identity and least-privilege database access; and
164
229
  - immutable audit/integrity evidence outside this package.