@tumbaland/backend-core 1.24.0 → 1.26.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.
Files changed (65) hide show
  1. package/dist/app/createBaseApp.d.ts +24 -0
  2. package/dist/app/createBaseApp.d.ts.map +1 -1
  3. package/dist/app/createBaseApp.js +20 -1
  4. package/dist/app/createBaseApp.js.map +1 -1
  5. package/dist/entitlements/client.d.ts.map +1 -1
  6. package/dist/entitlements/client.js +17 -1
  7. package/dist/entitlements/client.js.map +1 -1
  8. package/dist/entitlements/index.d.ts +3 -2
  9. package/dist/entitlements/index.d.ts.map +1 -1
  10. package/dist/entitlements/index.js +5 -4
  11. package/dist/entitlements/index.js.map +1 -1
  12. package/dist/entitlements/middleware.d.ts.map +1 -1
  13. package/dist/entitlements/middleware.js +8 -19
  14. package/dist/entitlements/middleware.js.map +1 -1
  15. package/dist/entitlements/reconcile.d.ts +74 -0
  16. package/dist/entitlements/reconcile.d.ts.map +1 -0
  17. package/dist/entitlements/reconcile.js +297 -0
  18. package/dist/entitlements/reconcile.js.map +1 -0
  19. package/dist/entitlements/types.d.ts +0 -8
  20. package/dist/entitlements/types.d.ts.map +1 -1
  21. package/dist/entitlements/usage.d.ts +1 -1
  22. package/dist/entitlements/usage.d.ts.map +1 -1
  23. package/dist/entitlements/usage.js +11 -20
  24. package/dist/entitlements/usage.js.map +1 -1
  25. package/dist/groups/client.d.ts +27 -0
  26. package/dist/groups/client.d.ts.map +1 -0
  27. package/dist/groups/client.js +153 -0
  28. package/dist/groups/client.js.map +1 -0
  29. package/dist/groups/index.d.ts +5 -0
  30. package/dist/groups/index.d.ts.map +1 -0
  31. package/dist/groups/index.js +10 -0
  32. package/dist/groups/index.js.map +1 -0
  33. package/dist/groups/subject.d.ts +30 -0
  34. package/dist/groups/subject.d.ts.map +1 -0
  35. package/dist/groups/subject.js +52 -0
  36. package/dist/groups/subject.js.map +1 -0
  37. package/dist/index.d.ts +1 -0
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +2 -0
  40. package/dist/index.js.map +1 -1
  41. package/package.json +1 -1
  42. package/src/app/createBaseApp.test.ts +31 -0
  43. package/src/app/createBaseApp.ts +28 -1
  44. package/src/entitlements/client.test.ts +30 -0
  45. package/src/entitlements/client.ts +18 -1
  46. package/src/entitlements/index.ts +4 -2
  47. package/src/entitlements/middleware.test.ts +9 -30
  48. package/src/entitlements/middleware.ts +8 -19
  49. package/src/entitlements/reconcile.test.ts +333 -0
  50. package/src/entitlements/reconcile.ts +384 -0
  51. package/src/entitlements/types.ts +0 -9
  52. package/src/entitlements/usage.test.ts +27 -31
  53. package/src/entitlements/usage.ts +12 -22
  54. package/src/groups/client.test.ts +215 -0
  55. package/src/groups/client.ts +182 -0
  56. package/src/groups/index.ts +5 -0
  57. package/src/groups/subject.test.ts +85 -0
  58. package/src/groups/subject.ts +50 -0
  59. package/src/index.ts +3 -0
  60. package/dist/entitlements/mode.d.ts +0 -10
  61. package/dist/entitlements/mode.d.ts.map +0 -1
  62. package/dist/entitlements/mode.js +0 -32
  63. package/dist/entitlements/mode.js.map +0 -1
  64. package/src/entitlements/mode.test.ts +0 -50
  65. package/src/entitlements/mode.ts +0 -28
@@ -18,6 +18,12 @@ export interface CreateBaseAppOptions {
18
18
  tracing?: boolean;
19
19
  /** Use requestLoggerWithMetrics (adds Prometheus histograms) instead of the plain requestLogger. Default true. */
20
20
  metrics?: boolean;
21
+ /**
22
+ * Value for Express's `trust proxy`. Defaults to trusting private/loopback
23
+ * addresses — see the note on tumbaland-proxy below. Pass `false` for a
24
+ * service exposed directly to clients with no proxy in front of it.
25
+ */
26
+ trustProxy?: Parameters<Express['set']>[1];
21
27
  }
22
28
  /**
23
29
  * Assembles the middleware stack every service was hand-rolling in its own
@@ -39,6 +45,24 @@ export interface CreateBaseAppOptions {
39
45
  * Services with non-standard body parsing (a webhook needing the raw body,
40
46
  * or conditional parsing per-route) should pass `parseJson`/`parseCookies:
41
47
  * false` and mount those themselves at the exact point they need to.
48
+ *
49
+ * `trust proxy` is on by default because nothing here is reached directly:
50
+ * every service sits behind tumbaland-proxy, which sets `X-Forwarded-For`.
51
+ * Left at Express's default (`false`) that header is ignored, which
52
+ * express-rate-limit reports as `ERR_ERL_UNEXPECTED_X_FORWARDED_FOR` — and
53
+ * it is right to: the limiter would then key every request in the cluster on
54
+ * the proxy's own container IP, so one busy client could exhaust the window
55
+ * for everyone.
56
+ *
57
+ * The value is `loopback, linklocal, uniquelocal` (private ranges) rather
58
+ * than a hop count, because the chain length differs per ingress path: a
59
+ * direct hit arrives as `client` + the proxy's own socket address, while
60
+ * traffic through the Cloudflare tunnel arrives as `client, 127.0.0.1` (the
61
+ * local cloudflared) + that same socket address. Express walks the chain
62
+ * right-to-left and stops at the first address it does not trust, so both
63
+ * paths land on the real client; a fixed number would be wrong for one of
64
+ * them. All the intermediaries are private addresses and the client is not,
65
+ * which is exactly the split this preset encodes.
42
66
  */
43
67
  export declare function createBaseApp(options?: CreateBaseAppOptions): Express;
44
68
  //# sourceMappingURL=createBaseApp.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"createBaseApp.d.ts","sourceRoot":"","sources":["../../src/app/createBaseApp.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAK3D,OAAO,EAAwB,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAI3F,MAAM,WAAW,oBAAoB;IACnC,8CAA8C;IAC9C,WAAW,CAAC,EAAE,qBAAqB,CAAC;IACpC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,cAAc,GAAG,KAAK,CAAC;IACrC,4IAA4I;IAC5I,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,6FAA6F;IAC7F,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kHAAkH;IAClH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,aAAa,CAAC,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAwBzE"}
1
+ {"version":3,"file":"createBaseApp.d.ts","sourceRoot":"","sources":["../../src/app/createBaseApp.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAK3D,OAAO,EAAwB,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAI3F,MAAM,WAAW,oBAAoB;IACnC,8CAA8C;IAC9C,WAAW,CAAC,EAAE,qBAAqB,CAAC;IACpC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,cAAc,GAAG,KAAK,CAAC;IACrC,4IAA4I;IAC5I,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,6FAA6F;IAC7F,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kHAAkH;IAClH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAC5C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAgB,aAAa,CAAC,OAAO,GAAE,oBAAyB,GAAG,OAAO,CA2BzE"}
@@ -32,10 +32,29 @@ const healthController_1 = require("../health/healthController");
32
32
  * Services with non-standard body parsing (a webhook needing the raw body,
33
33
  * or conditional parsing per-route) should pass `parseJson`/`parseCookies:
34
34
  * false` and mount those themselves at the exact point they need to.
35
+ *
36
+ * `trust proxy` is on by default because nothing here is reached directly:
37
+ * every service sits behind tumbaland-proxy, which sets `X-Forwarded-For`.
38
+ * Left at Express's default (`false`) that header is ignored, which
39
+ * express-rate-limit reports as `ERR_ERL_UNEXPECTED_X_FORWARDED_FOR` — and
40
+ * it is right to: the limiter would then key every request in the cluster on
41
+ * the proxy's own container IP, so one busy client could exhaust the window
42
+ * for everyone.
43
+ *
44
+ * The value is `loopback, linklocal, uniquelocal` (private ranges) rather
45
+ * than a hop count, because the chain length differs per ingress path: a
46
+ * direct hit arrives as `client` + the proxy's own socket address, while
47
+ * traffic through the Cloudflare tunnel arrives as `client, 127.0.0.1` (the
48
+ * local cloudflared) + that same socket address. Express walks the chain
49
+ * right-to-left and stops at the first address it does not trust, so both
50
+ * paths land on the real client; a fixed number would be wrong for one of
51
+ * them. All the intermediaries are private addresses and the client is not,
52
+ * which is exactly the split this preset encodes.
35
53
  */
36
54
  function createBaseApp(options = {}) {
37
- const { corsOptions, rateLimiter = security_1.standardRateLimiter, parseJson = true, parseCookies = true, tracing = true, metrics = true } = options;
55
+ const { corsOptions, rateLimiter = security_1.standardRateLimiter, parseJson = true, parseCookies = true, tracing = true, metrics = true, trustProxy = 'loopback, linklocal, uniquelocal' } = options;
38
56
  const app = (0, express_1.default)();
57
+ app.set('trust proxy', trustProxy);
39
58
  app.get('/health/live', healthController_1.healthLive);
40
59
  app.use(security_1.securityHeaders);
41
60
  if (rateLimiter)
@@ -1 +1 @@
1
- {"version":3,"file":"createBaseApp.js","sourceRoot":"","sources":["../../src/app/createBaseApp.ts"],"names":[],"mappings":";;;;;AAkDA,sCAwBC;AA1ED,sDAA2D;AAC3D,kEAAyC;AACzC,sDAA6D;AAC7D,wCAA+C;AAC/C,+DAAsF;AACtF,iEAA2F;AAC3F,qDAA8E;AAC9E,iEAAwD;AAsBxD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,SAAgB,aAAa,CAAC,UAAgC,EAAE;IAC9D,MAAM,EACJ,WAAW,EACX,WAAW,GAAG,8BAAmB,EACjC,SAAS,GAAG,IAAI,EAChB,YAAY,GAAG,IAAI,EACnB,OAAO,GAAG,IAAI,EACd,OAAO,GAAG,IAAI,EACf,GAAG,OAAO,CAAC;IAEZ,MAAM,GAAG,GAAG,IAAA,iBAAO,GAAE,CAAC;IAEtB,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,6BAAU,CAAC,CAAC;IAEpC,GAAG,CAAC,GAAG,CAAC,0BAAe,CAAC,CAAC;IACzB,IAAI,WAAW;QAAE,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACtC,GAAG,CAAC,GAAG,CAAC,mCAAqB,CAAC,CAAC;IAC/B,IAAI,OAAO;QAAE,GAAG,CAAC,GAAG,CAAC,2BAAiB,CAAC,CAAC;IACxC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,wCAAwB,CAAC,CAAC,CAAC,6BAAa,CAAC,CAAC;IAC5D,GAAG,CAAC,GAAG,CAAC,IAAA,qCAAoB,EAAC,WAAW,CAAC,CAAC,CAAC;IAC3C,IAAI,YAAY;QAAE,GAAG,CAAC,GAAG,CAAC,IAAA,uBAAY,GAAE,CAAC,CAAC;IAC1C,IAAI,SAAS;QAAE,GAAG,CAAC,GAAG,CAAC,iBAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAEvC,OAAO,GAAG,CAAC;AACb,CAAC"}
1
+ {"version":3,"file":"createBaseApp.js","sourceRoot":"","sources":["../../src/app/createBaseApp.ts"],"names":[],"mappings":";;;;;AA0EA,sCA2BC;AArGD,sDAA2D;AAC3D,kEAAyC;AACzC,sDAA6D;AAC7D,wCAA+C;AAC/C,+DAAsF;AACtF,iEAA2F;AAC3F,qDAA8E;AAC9E,iEAAwD;AA4BxD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,SAAgB,aAAa,CAAC,UAAgC,EAAE;IAC9D,MAAM,EACJ,WAAW,EACX,WAAW,GAAG,8BAAmB,EACjC,SAAS,GAAG,IAAI,EAChB,YAAY,GAAG,IAAI,EACnB,OAAO,GAAG,IAAI,EACd,OAAO,GAAG,IAAI,EACd,UAAU,GAAG,kCAAkC,EAChD,GAAG,OAAO,CAAC;IAEZ,MAAM,GAAG,GAAG,IAAA,iBAAO,GAAE,CAAC;IAEtB,GAAG,CAAC,GAAG,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;IAEnC,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,6BAAU,CAAC,CAAC;IAEpC,GAAG,CAAC,GAAG,CAAC,0BAAe,CAAC,CAAC;IACzB,IAAI,WAAW;QAAE,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACtC,GAAG,CAAC,GAAG,CAAC,mCAAqB,CAAC,CAAC;IAC/B,IAAI,OAAO;QAAE,GAAG,CAAC,GAAG,CAAC,2BAAiB,CAAC,CAAC;IACxC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,wCAAwB,CAAC,CAAC,CAAC,6BAAa,CAAC,CAAC;IAC5D,GAAG,CAAC,GAAG,CAAC,IAAA,qCAAoB,EAAC,WAAW,CAAC,CAAC,CAAC;IAC3C,IAAI,YAAY;QAAE,GAAG,CAAC,GAAG,CAAC,IAAA,uBAAY,GAAE,CAAC,CAAC;IAC1C,IAAI,SAAS;QAAE,GAAG,CAAC,GAAG,CAAC,iBAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAEvC,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/entitlements/client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAsHvC;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAoB1E;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAE1D;AAED,qFAAqF;AACrF,wBAAgB,sBAAsB,IAAI,IAAI,CAG7C"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/entitlements/client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAuIvC;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAoB1E;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAE1D;AAED,qFAAqF;AACrF,wBAAgB,sBAAsB,IAAI,IAAI,CAG7C"}
@@ -58,8 +58,24 @@ function fallbackEntitlements(email) {
58
58
  stale: true
59
59
  };
60
60
  }
61
+ /**
62
+ * Prefers the container-network address over the public hostname.
63
+ *
64
+ * `PAYMENT_API_URL` cannot simply be pointed inward: payment-front's entrypoint
65
+ * templates that same variable into the `config.json` the *browser* downloads,
66
+ * so a Docker-internal value there breaks the subscription and checkout pages.
67
+ * One variable, two consumers with incompatible needs — this is the server-side
68
+ * half of it.
69
+ *
70
+ * Falling back keeps local dev (where only `PAYMENT_API_URL` is set) and any
71
+ * un-migrated deployment working; it just takes the long way round, out through
72
+ * the proxy and back, carrying the internal token across the public edge.
73
+ */
74
+ function internalPaymentUrl() {
75
+ return process.env.PAYMENT_INTERNAL_URL || process.env.PAYMENT_API_URL;
76
+ }
61
77
  async function fetchEntitlements(email) {
62
- const baseUrl = process.env.PAYMENT_API_URL;
78
+ const baseUrl = internalPaymentUrl();
63
79
  const token = process.env.INTERNAL_SERVICE_TOKEN;
64
80
  const serviceId = process.env.SERVICE_NAME || 'unknown-service';
65
81
  if (!baseUrl || !token) {
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/entitlements/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/entitlements/client.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,12 @@
1
1
  export { UNLIMITED, FALLBACK_PLAN, STAFF_PLAN, applyLimits, METER_KEYS, FEATURE_KEYS, METER_DEFINITIONS, FEATURE_DEFINITIONS, DEFAULT_PLAN_LIMITS, ENTITLEMENT_CATALOG, resolveLimits, normalizeLimits, meterPeriod, isMeterKey, isFeatureKey, fitsWithin } from './definitions';
2
2
  export type { MeterKey, FeatureKey, MeterPeriod, MeterDefinition, FeatureDefinition, PlanLimits, PartialPlanLimits } from './definitions';
3
- export type { Entitlements, EntitlementsMode } from './types';
4
- export { getEntitlementsMode, resetEntitlementsModeWarning } from './mode';
3
+ export type { Entitlements } from './types';
5
4
  export { UsageMeter, currentPeriod } from './UsageMeter';
6
5
  export type { IUsageMeter } from './UsageMeter';
7
6
  export { getUsage, getUsageSnapshot, checkQuota, consumeQuota, releaseQuota, setUsage } from './usage';
8
7
  export type { QuotaRequest } from './usage';
8
+ export { reconcileUsageMeters, runUsageReconciliation, RECONCILED_METERS } from './reconcile';
9
+ export type { ReconcileOptions, ReconcileReport, MeterChange, OrphanedMeter } from './reconcile';
9
10
  export { getEntitlements, invalidateEntitlements, clearEntitlementsCache } from './client';
10
11
  export { loadEntitlements, requireEntitlement, requireQuota, retentionFloor } from './middleware';
11
12
  export type { EntitlementOptions, QuotaOptions, SubjectResolver } from './middleware';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/entitlements/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,aAAa,EACb,UAAU,EACV,WAAW,EACX,UAAU,EACV,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,EACb,eAAe,EACf,WAAW,EACX,UAAU,EACV,YAAY,EACZ,UAAU,EACX,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,QAAQ,EACR,UAAU,EACV,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,UAAU,EACV,iBAAiB,EAClB,MAAM,eAAe,CAAC;AAEvB,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,4BAA4B,EAAE,MAAM,QAAQ,CAAC;AAE3E,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACzD,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACvG,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAE3F,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAClG,YAAY,EAAE,kBAAkB,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/entitlements/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,aAAa,EACb,UAAU,EACV,WAAW,EACX,UAAU,EACV,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,EACb,eAAe,EACf,WAAW,EACX,UAAU,EACV,YAAY,EACZ,UAAU,EACX,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,QAAQ,EACR,UAAU,EACV,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,UAAU,EACV,iBAAiB,EAClB,MAAM,eAAe,CAAC;AAEvB,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACzD,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACvG,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC9F,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjG,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAE3F,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAClG,YAAY,EAAE,kBAAkB,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.retentionFloor = exports.requireQuota = exports.requireEntitlement = exports.loadEntitlements = exports.clearEntitlementsCache = exports.invalidateEntitlements = exports.getEntitlements = exports.setUsage = exports.releaseQuota = exports.consumeQuota = exports.checkQuota = exports.getUsageSnapshot = exports.getUsage = exports.currentPeriod = exports.UsageMeter = exports.resetEntitlementsModeWarning = exports.getEntitlementsMode = exports.fitsWithin = exports.isFeatureKey = exports.isMeterKey = exports.meterPeriod = exports.normalizeLimits = exports.resolveLimits = exports.ENTITLEMENT_CATALOG = exports.DEFAULT_PLAN_LIMITS = exports.FEATURE_DEFINITIONS = exports.METER_DEFINITIONS = exports.FEATURE_KEYS = exports.METER_KEYS = exports.applyLimits = exports.STAFF_PLAN = exports.FALLBACK_PLAN = exports.UNLIMITED = void 0;
3
+ exports.retentionFloor = exports.requireQuota = exports.requireEntitlement = exports.loadEntitlements = exports.clearEntitlementsCache = exports.invalidateEntitlements = exports.getEntitlements = exports.RECONCILED_METERS = exports.runUsageReconciliation = exports.reconcileUsageMeters = exports.setUsage = exports.releaseQuota = exports.consumeQuota = exports.checkQuota = exports.getUsageSnapshot = exports.getUsage = exports.currentPeriod = exports.UsageMeter = exports.fitsWithin = exports.isFeatureKey = exports.isMeterKey = exports.meterPeriod = exports.normalizeLimits = exports.resolveLimits = exports.ENTITLEMENT_CATALOG = exports.DEFAULT_PLAN_LIMITS = exports.FEATURE_DEFINITIONS = exports.METER_DEFINITIONS = exports.FEATURE_KEYS = exports.METER_KEYS = exports.applyLimits = exports.STAFF_PLAN = exports.FALLBACK_PLAN = exports.UNLIMITED = void 0;
4
4
  var definitions_1 = require("./definitions");
5
5
  Object.defineProperty(exports, "UNLIMITED", { enumerable: true, get: function () { return definitions_1.UNLIMITED; } });
6
6
  Object.defineProperty(exports, "FALLBACK_PLAN", { enumerable: true, get: function () { return definitions_1.FALLBACK_PLAN; } });
@@ -18,9 +18,6 @@ Object.defineProperty(exports, "meterPeriod", { enumerable: true, get: function
18
18
  Object.defineProperty(exports, "isMeterKey", { enumerable: true, get: function () { return definitions_1.isMeterKey; } });
19
19
  Object.defineProperty(exports, "isFeatureKey", { enumerable: true, get: function () { return definitions_1.isFeatureKey; } });
20
20
  Object.defineProperty(exports, "fitsWithin", { enumerable: true, get: function () { return definitions_1.fitsWithin; } });
21
- var mode_1 = require("./mode");
22
- Object.defineProperty(exports, "getEntitlementsMode", { enumerable: true, get: function () { return mode_1.getEntitlementsMode; } });
23
- Object.defineProperty(exports, "resetEntitlementsModeWarning", { enumerable: true, get: function () { return mode_1.resetEntitlementsModeWarning; } });
24
21
  var UsageMeter_1 = require("./UsageMeter");
25
22
  Object.defineProperty(exports, "UsageMeter", { enumerable: true, get: function () { return UsageMeter_1.UsageMeter; } });
26
23
  Object.defineProperty(exports, "currentPeriod", { enumerable: true, get: function () { return UsageMeter_1.currentPeriod; } });
@@ -31,6 +28,10 @@ Object.defineProperty(exports, "checkQuota", { enumerable: true, get: function (
31
28
  Object.defineProperty(exports, "consumeQuota", { enumerable: true, get: function () { return usage_1.consumeQuota; } });
32
29
  Object.defineProperty(exports, "releaseQuota", { enumerable: true, get: function () { return usage_1.releaseQuota; } });
33
30
  Object.defineProperty(exports, "setUsage", { enumerable: true, get: function () { return usage_1.setUsage; } });
31
+ var reconcile_1 = require("./reconcile");
32
+ Object.defineProperty(exports, "reconcileUsageMeters", { enumerable: true, get: function () { return reconcile_1.reconcileUsageMeters; } });
33
+ Object.defineProperty(exports, "runUsageReconciliation", { enumerable: true, get: function () { return reconcile_1.runUsageReconciliation; } });
34
+ Object.defineProperty(exports, "RECONCILED_METERS", { enumerable: true, get: function () { return reconcile_1.RECONCILED_METERS; } });
34
35
  var client_1 = require("./client");
35
36
  Object.defineProperty(exports, "getEntitlements", { enumerable: true, get: function () { return client_1.getEntitlements; } });
36
37
  Object.defineProperty(exports, "invalidateEntitlements", { enumerable: true, get: function () { return client_1.invalidateEntitlements; } });
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/entitlements/index.ts"],"names":[],"mappings":";;;AAAA,6CAiBuB;AAhBrB,wGAAA,SAAS,OAAA;AACT,4GAAA,aAAa,OAAA;AACb,yGAAA,UAAU,OAAA;AACV,0GAAA,WAAW,OAAA;AACX,yGAAA,UAAU,OAAA;AACV,2GAAA,YAAY,OAAA;AACZ,gHAAA,iBAAiB,OAAA;AACjB,kHAAA,mBAAmB,OAAA;AACnB,kHAAA,mBAAmB,OAAA;AACnB,kHAAA,mBAAmB,OAAA;AACnB,4GAAA,aAAa,OAAA;AACb,8GAAA,eAAe,OAAA;AACf,0GAAA,WAAW,OAAA;AACX,yGAAA,UAAU,OAAA;AACV,2GAAA,YAAY,OAAA;AACZ,yGAAA,UAAU,OAAA;AAaZ,+BAA2E;AAAlE,2GAAA,mBAAmB,OAAA;AAAE,oHAAA,4BAA4B,OAAA;AAE1D,2CAAyD;AAAhD,wGAAA,UAAU,OAAA;AAAE,2GAAA,aAAa,OAAA;AAElC,iCAAuG;AAA9F,iGAAA,QAAQ,OAAA;AAAE,yGAAA,gBAAgB,OAAA;AAAE,mGAAA,UAAU,OAAA;AAAE,qGAAA,YAAY,OAAA;AAAE,qGAAA,YAAY,OAAA;AAAE,iGAAA,QAAQ,OAAA;AAGrF,mCAA2F;AAAlF,yGAAA,eAAe,OAAA;AAAE,gHAAA,sBAAsB,OAAA;AAAE,gHAAA,sBAAsB,OAAA;AAExE,2CAAkG;AAAzF,8GAAA,gBAAgB,OAAA;AAAE,gHAAA,kBAAkB,OAAA;AAAE,0GAAA,YAAY,OAAA;AAAE,4GAAA,cAAc,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/entitlements/index.ts"],"names":[],"mappings":";;;AAAA,6CAiBuB;AAhBrB,wGAAA,SAAS,OAAA;AACT,4GAAA,aAAa,OAAA;AACb,yGAAA,UAAU,OAAA;AACV,0GAAA,WAAW,OAAA;AACX,yGAAA,UAAU,OAAA;AACV,2GAAA,YAAY,OAAA;AACZ,gHAAA,iBAAiB,OAAA;AACjB,kHAAA,mBAAmB,OAAA;AACnB,kHAAA,mBAAmB,OAAA;AACnB,kHAAA,mBAAmB,OAAA;AACnB,4GAAA,aAAa,OAAA;AACb,8GAAA,eAAe,OAAA;AACf,0GAAA,WAAW,OAAA;AACX,yGAAA,UAAU,OAAA;AACV,2GAAA,YAAY,OAAA;AACZ,yGAAA,UAAU,OAAA;AAcZ,2CAAyD;AAAhD,wGAAA,UAAU,OAAA;AAAE,2GAAA,aAAa,OAAA;AAElC,iCAAuG;AAA9F,iGAAA,QAAQ,OAAA;AAAE,yGAAA,gBAAgB,OAAA;AAAE,mGAAA,UAAU,OAAA;AAAE,qGAAA,YAAY,OAAA;AAAE,qGAAA,YAAY,OAAA;AAAE,iGAAA,QAAQ,OAAA;AAGrF,yCAA8F;AAArF,iHAAA,oBAAoB,OAAA;AAAE,mHAAA,sBAAsB,OAAA;AAAE,8GAAA,iBAAiB,OAAA;AAGxE,mCAA2F;AAAlF,yGAAA,eAAe,OAAA;AAAE,gHAAA,sBAAsB,OAAA;AAAE,gHAAA,sBAAsB,OAAA;AAExE,2CAAkG;AAAzF,8GAAA,gBAAgB,OAAA;AAAE,gHAAA,kBAAkB,OAAA;AAAE,0GAAA,YAAY,OAAA;AAAE,4GAAA,cAAc,OAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/entitlements/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAGlD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAa,MAAM,eAAe,CAAC;AAIhE,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,OAAO,CAAC;QAChB,UAAU,OAAO;YACf,uGAAuG;YACvG,YAAY,CAAC,EAAE,YAAY,CAAC;SAC7B;KACF;CACF;AAED;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;AAEjG,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,eAAe,CAAC;CAC3B;AAID;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,GAAE,eAAgC,GAAG,OAAO,CAAC,YAAY,CAAC,CASrH;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,GAAE,kBAAuB,GAAG,cAAc,CA+BxG;AAED,MAAM,WAAW,YAAa,SAAQ,kBAAkB;IACtD;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,OAAO,KAAK,MAAM,CAAC,CAAC;CAC9C;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,GAAE,YAAiB,GAAG,cAAc,CAoBxF;AAED;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,GAAE,IAAiB,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAQhG"}
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/entitlements/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAGlD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAa,MAAM,eAAe,CAAC;AAGhE,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,OAAO,CAAC;QAChB,UAAU,OAAO;YACf,uGAAuG;YACvG,YAAY,CAAC,EAAE,YAAY,CAAC;SAC7B;KACF;CACF;AAED;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;AAEjG,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,eAAe,CAAC;CAC3B;AAID;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,GAAE,eAAgC,GAAG,OAAO,CAAC,YAAY,CAAC,CASrH;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,GAAE,kBAAuB,GAAG,cAAc,CAyBxG;AAED,MAAM,WAAW,YAAa,SAAQ,kBAAkB;IACtD;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,OAAO,KAAK,MAAM,CAAC,CAAC;CAC9C;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,GAAE,YAAiB,GAAG,cAAc,CAkBxF;AAED;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,GAAE,IAAiB,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAMhG"}
@@ -12,7 +12,6 @@ const HttpError_1 = require("../errors/HttpError");
12
12
  const definitions_1 = require("./definitions");
13
13
  const client_1 = require("./client");
14
14
  const usage_1 = require("./usage");
15
- const mode_1 = require("./mode");
16
15
  const defaultSubject = req => req.user?.email;
17
16
  /**
18
17
  * Resolves and caches entitlements on the request. Two checks on one route
@@ -35,23 +34,17 @@ async function loadEntitlements(req, resolve = defaultSubject) {
35
34
  function requireEntitlement(feature, options = {}) {
36
35
  return async (req, _res, next) => {
37
36
  try {
38
- const mode = (0, mode_1.getEntitlementsMode)();
39
- if (mode === 'off')
40
- return next();
41
37
  const entitlements = await loadEntitlements(req, options.subject);
42
38
  if (entitlements.limits.features[feature])
43
39
  return next();
44
- if (mode === 'observe') {
45
- logger_1.default.info('entitlement.would_block', {
46
- event: 'entitlement.would_block',
47
- feature,
48
- subjectId: entitlements.email,
49
- planCode: entitlements.planCode,
50
- route: req.originalUrl,
51
- stale: entitlements.stale === true
52
- });
53
- return next();
54
- }
40
+ logger_1.default.info('entitlement.blocked', {
41
+ event: 'entitlement.blocked',
42
+ feature,
43
+ subjectId: entitlements.email,
44
+ planCode: entitlements.planCode,
45
+ route: req.originalUrl,
46
+ stale: entitlements.stale === true
47
+ });
55
48
  throw new HttpError_1.PaymentRequiredError(`Your plan does not include ${feature}`, {
56
49
  code: 'FEATURE_NOT_IN_PLAN',
57
50
  feature,
@@ -71,8 +64,6 @@ function requireEntitlement(feature, options = {}) {
71
64
  function requireQuota(meter, options = {}) {
72
65
  return async (req, _res, next) => {
73
66
  try {
74
- if ((0, mode_1.getEntitlementsMode)() === 'off')
75
- return next();
76
67
  const entitlements = await loadEntitlements(req, options.subject);
77
68
  const amount = typeof options.amount === 'function' ? options.amount(req) : (options.amount ?? 1);
78
69
  await (0, usage_1.checkQuota)({
@@ -98,8 +89,6 @@ function requireQuota(meter, options = {}) {
98
89
  * price history it depends on is not.
99
90
  */
100
91
  async function retentionFloor(email, now = new Date()) {
101
- if ((0, mode_1.getEntitlementsMode)() !== 'enforce')
102
- return null;
103
92
  const { limits } = await (0, client_1.getEntitlements)(email);
104
93
  const days = limits.retentionDays;
105
94
  if (days === definitions_1.UNLIMITED || days < 0)
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/entitlements/middleware.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/entitlements/middleware.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ import { MeterKey } from './definitions';
2
+ /**
3
+ * Rebuild the cumulative usage meters from the data they describe.
4
+ *
5
+ * **Why this can exist at all:** every meter reconciled here is *derived*.
6
+ * `storageBytes` is the sum of photo sizes, `trackedTickers` the count of
7
+ * active symbols, `seats` the members of the groups a subject owns — in each
8
+ * case the underlying collection is the record and the counter is only a cache
9
+ * of it, kept hot because a quota check cannot afford the aggregation. So the
10
+ * counter can always be recomputed, and reconciliation is cache invalidation.
11
+ *
12
+ * `aiJobs` is deliberately absent, and its absence is the same rule read the
13
+ * other way: nothing records that a GPU job happened except the counter itself,
14
+ * so there is no truth to recompute it from. That is precisely why
15
+ * `consumeQuota` rolls its increment back on rejection rather than leaving it —
16
+ * a leaked increment on that meter is permanent, where here it is temporary.
17
+ *
18
+ * **On racing with live writes:** a `consumeQuota` landing between the
19
+ * aggregation and the write is lost. That is tolerable for exactly the reason
20
+ * above — the next run re-derives the same number from source and converges —
21
+ * so this is scheduled at a quiet hour rather than defended with a lock.
22
+ *
23
+ * Reads collections owned by other services through the raw driver rather than
24
+ * mongoose models. They are not this library's documents to model, every
25
+ * service shares one database, and going through the driver avoids registering
26
+ * a second model for a schema that already exists elsewhere.
27
+ */
28
+ /** Meters whose value can be recomputed from source data. See the note above. */
29
+ export declare const RECONCILED_METERS: readonly MeterKey[];
30
+ export interface ReconcileOptions {
31
+ /** Write the corrections. Default false — the caller must opt in to mutating. */
32
+ apply?: boolean;
33
+ /** Restrict to a single subject, for a targeted repair. */
34
+ subject?: string;
35
+ }
36
+ export interface MeterChange {
37
+ subjectId: string;
38
+ meter: MeterKey;
39
+ /** `null` when no counter existed yet. */
40
+ from: number | null;
41
+ to: number;
42
+ }
43
+ export interface OrphanedMeter {
44
+ subjectId: string;
45
+ meter: string;
46
+ count: number;
47
+ }
48
+ export interface ReconcileReport {
49
+ applied: boolean;
50
+ scannedUsers: number;
51
+ /** Subjects with any attributable usage, before any `subject` filter. */
52
+ subjects: number;
53
+ expected: Record<string, Record<MeterKey, number>>;
54
+ changes: MeterChange[];
55
+ written: number;
56
+ orphanedMeters: OrphanedMeter[];
57
+ warnings: string[];
58
+ }
59
+ /**
60
+ * Recompute every derived meter and, with `apply`, write back the ones that
61
+ * disagree.
62
+ *
63
+ * Idempotent: it computes absolute values and writes only differences, so a
64
+ * second run in a row is a no-op.
65
+ */
66
+ export declare function reconcileUsageMeters(options?: ReconcileOptions): Promise<ReconcileReport>;
67
+ /**
68
+ * Run a reconciliation and log the outcome. The scheduled entry point.
69
+ *
70
+ * Never throws: this runs from a cron callback with no caller to catch it, and
71
+ * an unhandled rejection there takes the process down over a housekeeping job.
72
+ */
73
+ export declare function runUsageReconciliation(): Promise<ReconcileReport | null>;
74
+ //# sourceMappingURL=reconcile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconcile.d.ts","sourceRoot":"","sources":["../../src/entitlements/reconcile.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGzC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,iFAAiF;AACjF,eAAO,MAAM,iBAAiB,EAAE,SAAS,QAAQ,EAAgD,CAAC;AAElG,MAAM,WAAW,gBAAgB;IAC/B,iFAAiF;IACjF,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,QAAQ,CAAC;IAChB,0CAA0C;IAC1C,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,yEAAyE;IACzE,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;IACnD,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AA2LD;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,eAAe,CAAC,CAkFnG;AAED;;;;;GAKG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAiC9E"}