@i4e/invest4edu-access-core 0.29.0 → 0.30.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@i4e/invest4edu-access-core",
3
- "version": "0.29.0",
3
+ "version": "0.30.0",
4
4
  "description": "Shared access-control primitives for NeoFindesk: tenant keystone, role capabilities, reportee tree, feature flags, and the unified access engine (registry schema, snapshot resolver, visibleWhen).",
5
5
  "type": "module",
6
6
  "exports": {
@@ -210,8 +210,28 @@ export function createEntitlementStore({
210
210
  ? { ...creditRows[0], quota: result.quota, overage_policy: result.overage_policy || creditRows[0].overage_policy }
211
211
  : null;
212
212
 
213
+ /**
214
+ * A CEILING survives credits mode.
215
+ *
216
+ * `limit` shapes a response — "your list shows 5" — and is read on every request without
217
+ * ever being spent. A PRICE is what a use costs. They are orthogonal, and the two live on
218
+ * different fields for exactly that reason.
219
+ *
220
+ * Without this line the credits branch returned the wallet's numbers and no `limit` at
221
+ * all, so a consumer reading `ent.limit` (NFD AI's stock-tips shaper does) saw nothing
222
+ * and applied no ceiling. A free plan promising five stock ideas silently served every
223
+ * one of them — the paywall looked configured and was not.
224
+ *
225
+ * Same UNSET-vs-0 care as count mode: null means "no ceiling", 0 means "show nothing".
226
+ */
227
+ const rawCeiling = svcRow.quota;
228
+ const ceiling = rawCeiling === null || rawCeiling === undefined || rawCeiling === ""
229
+ ? null
230
+ : Number(rawCeiling);
231
+
213
232
  return {
214
233
  ...result,
234
+ limit: ceiling !== null && Number.isFinite(ceiling) && ceiling >= 0 ? ceiling : null,
215
235
  mode: "credits",
216
236
  carriedSubjectType: subjectType,
217
237
  carriedSubjectId: subjectId,