@tumbaland/backend-core 1.50.0 → 1.52.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.
@@ -6,5 +6,6 @@ export { authenticateAgent, requireScope, denyApiKeys } from './middleware';
6
6
  export type { ApiKeyContext } from './middleware';
7
7
  export { API_KEY_SCOPES, isApiKeyScope, PERSONAL_TENANT, groupIdOf, groupIdsOf, readTenants } from './types';
8
8
  export type { ApiKeyScope, ApiKeySummary, ApiKeyVerification, ApiKeyRejection, ApiKeyTenant, Tenant } from './types';
9
- export { looksLikeApiKey, displayPrefix, isEncryptionConfigured, resetEncryptionKeyCache } from './crypto';
9
+ export { looksLikeApiKey, displayPrefix, isEncryptionConfigured, resetEncryptionKeyCache, encryptSecret, decryptSecret } from './crypto';
10
+ export type { SealedSecret } from './crypto';
10
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/apiKeys/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EACL,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,YAAY,EACb,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC5E,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EACL,cAAc,EACd,aAAa,EACb,eAAe,EACf,SAAS,EACT,UAAU,EACV,WAAW,EACZ,MAAM,SAAS,CAAC;AACjB,YAAY,EACV,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,eAAe,EACf,YAAY,EACZ,MAAM,EACP,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,eAAe,EACf,aAAa,EACb,sBAAsB,EACtB,uBAAuB,EACxB,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/apiKeys/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EACL,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,YAAY,EACb,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC5E,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EACL,cAAc,EACd,aAAa,EACb,eAAe,EACf,SAAS,EACT,UAAU,EACV,WAAW,EACZ,MAAM,SAAS,CAAC;AACjB,YAAY,EACV,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,eAAe,EACf,YAAY,EACZ,MAAM,EACP,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,eAAe,EACf,aAAa,EACb,sBAAsB,EACtB,uBAAuB,EACvB,aAAa,EACb,aAAa,EACd,MAAM,UAAU,CAAC;AAClB,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.resetEncryptionKeyCache = exports.isEncryptionConfigured = exports.displayPrefix = exports.looksLikeApiKey = exports.readTenants = exports.groupIdsOf = exports.groupIdOf = exports.PERSONAL_TENANT = exports.isApiKeyScope = exports.API_KEY_SCOPES = exports.denyApiKeys = exports.requireScope = exports.authenticateAgent = exports.verifyApiKey = exports.deleteApiKey = exports.revokeApiKey = exports.revealApiKey = exports.listApiKeys = exports.createApiKey = exports.ApiKey = void 0;
3
+ exports.decryptSecret = exports.encryptSecret = exports.resetEncryptionKeyCache = exports.isEncryptionConfigured = exports.displayPrefix = exports.looksLikeApiKey = exports.readTenants = exports.groupIdsOf = exports.groupIdOf = exports.PERSONAL_TENANT = exports.isApiKeyScope = exports.API_KEY_SCOPES = exports.denyApiKeys = exports.requireScope = exports.authenticateAgent = exports.verifyApiKey = exports.deleteApiKey = exports.revokeApiKey = exports.revealApiKey = exports.listApiKeys = exports.createApiKey = exports.ApiKey = void 0;
4
4
  var ApiKey_1 = require("./ApiKey");
5
5
  Object.defineProperty(exports, "ApiKey", { enumerable: true, get: function () { return ApiKey_1.ApiKey; } });
6
6
  var service_1 = require("./service");
@@ -26,4 +26,6 @@ Object.defineProperty(exports, "looksLikeApiKey", { enumerable: true, get: funct
26
26
  Object.defineProperty(exports, "displayPrefix", { enumerable: true, get: function () { return crypto_1.displayPrefix; } });
27
27
  Object.defineProperty(exports, "isEncryptionConfigured", { enumerable: true, get: function () { return crypto_1.isEncryptionConfigured; } });
28
28
  Object.defineProperty(exports, "resetEncryptionKeyCache", { enumerable: true, get: function () { return crypto_1.resetEncryptionKeyCache; } });
29
+ Object.defineProperty(exports, "encryptSecret", { enumerable: true, get: function () { return crypto_1.encryptSecret; } });
30
+ Object.defineProperty(exports, "decryptSecret", { enumerable: true, get: function () { return crypto_1.decryptSecret; } });
29
31
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/apiKeys/index.ts"],"names":[],"mappings":";;;AAAA,mCAAkC;AAAzB,gGAAA,MAAM,OAAA;AAEf,qCAOmB;AANjB,uGAAA,YAAY,OAAA;AACZ,sGAAA,WAAW,OAAA;AACX,uGAAA,YAAY,OAAA;AACZ,uGAAA,YAAY,OAAA;AACZ,uGAAA,YAAY,OAAA;AACZ,uGAAA,YAAY,OAAA;AAGd,2CAA4E;AAAnE,+GAAA,iBAAiB,OAAA;AAAE,0GAAA,YAAY,OAAA;AAAE,yGAAA,WAAW,OAAA;AAErD,iCAOiB;AANf,uGAAA,cAAc,OAAA;AACd,sGAAA,aAAa,OAAA;AACb,wGAAA,eAAe,OAAA;AACf,kGAAA,SAAS,OAAA;AACT,mGAAA,UAAU,OAAA;AACV,oGAAA,WAAW,OAAA;AAUb,mCAKkB;AAJhB,yGAAA,eAAe,OAAA;AACf,uGAAA,aAAa,OAAA;AACb,gHAAA,sBAAsB,OAAA;AACtB,iHAAA,uBAAuB,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/apiKeys/index.ts"],"names":[],"mappings":";;;AAAA,mCAAkC;AAAzB,gGAAA,MAAM,OAAA;AAEf,qCAOmB;AANjB,uGAAA,YAAY,OAAA;AACZ,sGAAA,WAAW,OAAA;AACX,uGAAA,YAAY,OAAA;AACZ,uGAAA,YAAY,OAAA;AACZ,uGAAA,YAAY,OAAA;AACZ,uGAAA,YAAY,OAAA;AAGd,2CAA4E;AAAnE,+GAAA,iBAAiB,OAAA;AAAE,0GAAA,YAAY,OAAA;AAAE,yGAAA,WAAW,OAAA;AAErD,iCAOiB;AANf,uGAAA,cAAc,OAAA;AACd,sGAAA,aAAa,OAAA;AACb,wGAAA,eAAe,OAAA;AACf,kGAAA,SAAS,OAAA;AACT,mGAAA,UAAU,OAAA;AACV,oGAAA,WAAW,OAAA;AAUb,mCAOkB;AANhB,yGAAA,eAAe,OAAA;AACf,uGAAA,aAAa,OAAA;AACb,gHAAA,sBAAsB,OAAA;AACtB,iHAAA,uBAAuB,OAAA;AACvB,uGAAA,aAAa,OAAA;AACb,uGAAA,aAAa,OAAA"}
@@ -17,7 +17,7 @@
17
17
  * - `ENTITLEMENT_CATALOG`, the metadata an admin UI renders its form from,
18
18
  * so adding a meter needs no frontend change.
19
19
  */
20
- export type MeterKey = 'storageBytes' | 'aiJobs' | 'trackedTickers' | 'seats';
20
+ export type MeterKey = 'storageBytes' | 'aiJobs' | 'trackedTickers' | 'seats' | 'assistantSpend';
21
21
  /**
22
22
  * Deliberately small. The portfolio planner is NOT a feature flag — it is gated
23
23
  * by `retentionDays` via the price-history range, because the planner runs
@@ -1 +1 @@
1
- {"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/entitlements/definitions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,MAAM,QAAQ,GAAG,cAAc,GAAG,QAAQ,GAAG,gBAAgB,GAAG,OAAO,CAAC;AAE9E;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG,aAAa,CAAC;AAEvC,8FAA8F;AAC9F,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,OAAO,CAAC;AAE1C,2FAA2F;AAC3F,eAAO,MAAM,SAAS,KAAK,CAAC;AAE5B,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,QAAQ,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,oGAAoG;IACpG,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IACxB,MAAM,EAAE,WAAW,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,UAAU,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,iBAAiB,EAAE,SAAS,eAAe,EA6B9C,CAAC;AAEX,eAAO,MAAM,mBAAmB,EAAE,SAAS,iBAAiB,EAMlD,CAAC;AAEX,eAAO,MAAM,UAAU,EAAE,SAAS,QAAQ,EAAsC,CAAC;AACjF,eAAO,MAAM,YAAY,EAAE,SAAS,UAAU,EAAwC,CAAC;AAMvF,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,WAAW,CAExD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,QAAQ,CAE3D;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,UAAU,CAE/D;AAED,MAAM,WAAW,UAAU;IACzB,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACjC,QAAQ,EAAE,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACtC,6EAA6E;IAC7E,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,8EAA8E;AAC9E,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACzC,QAAQ,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC5C,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAID;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAsCpE,CAAC;AAEF,iDAAiD;AACjD,eAAO,MAAM,UAAU,UAAU,CAAC;AAElC,eAAO,MAAM,aAAa,SAAS,CAAC;AAEpC;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,UAAU,CAG3D;AAiBD;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,CAAC,EAAE,iBAAiB,GAAG,IAAI,GAAG,UAAU,CAc1F;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,CAAC,EAAE,iBAAiB,GAAG,IAAI,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,UAAU,CAE/F;AAED,6EAA6E;AAC7E,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,SAAI,GAAG,OAAO,CAG3E;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;CAa/B,CAAC"}
1
+ {"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/entitlements/definitions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,MAAM,QAAQ,GAAG,cAAc,GAAG,QAAQ,GAAG,gBAAgB,GAAG,OAAO,GAAG,gBAAgB,CAAC;AAEjG;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG,aAAa,CAAC;AAEvC,8FAA8F;AAC9F,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,OAAO,CAAC;AAE1C,2FAA2F;AAC3F,eAAO,MAAM,SAAS,KAAK,CAAC;AAE5B,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,QAAQ,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,oGAAoG;IACpG,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IACxB,MAAM,EAAE,WAAW,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,UAAU,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,iBAAiB,EAAE,SAAS,eAAe,EAqC9C,CAAC;AAEX,eAAO,MAAM,mBAAmB,EAAE,SAAS,iBAAiB,EAMlD,CAAC;AAEX,eAAO,MAAM,UAAU,EAAE,SAAS,QAAQ,EAAsC,CAAC;AACjF,eAAO,MAAM,YAAY,EAAE,SAAS,UAAU,EAAwC,CAAC;AAMvF,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,WAAW,CAExD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,QAAQ,CAE3D;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,UAAU,CAE/D;AAED,MAAM,WAAW,UAAU;IACzB,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACjC,QAAQ,EAAE,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACtC,6EAA6E;IAC7E,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,8EAA8E;AAC9E,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACzC,QAAQ,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC5C,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAID;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CA4CpE,CAAC;AAEF,iDAAiD;AACjD,eAAO,MAAM,UAAU,UAAU,CAAC;AAElC,eAAO,MAAM,aAAa,SAAS,CAAC;AAEpC;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,UAAU,CAG3D;AAiBD;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,CAAC,EAAE,iBAAiB,GAAG,IAAI,GAAG,UAAU,CAc1F;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,CAAC,EAAE,iBAAiB,GAAG,IAAI,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,UAAU,CAE/F;AAED,6EAA6E;AAC7E,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,SAAI,GAAG,OAAO,CAG3E;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;CAa/B,CAAC"}
@@ -57,6 +57,13 @@ exports.METER_DEFINITIONS = [
57
57
  unit: 'count',
58
58
  period: 'ALL',
59
59
  description: 'Members that may join groups owned by the user, including the owner.'
60
+ },
61
+ {
62
+ key: 'assistantSpend',
63
+ label: 'Chat assistant allowance',
64
+ unit: 'count',
65
+ period: 'MONTH',
66
+ description: 'What the chat assistants may cost per calendar month, charged to whoever asks. One unit is a ten-thousandth of a dollar, so 10000 is $1.'
60
67
  }
61
68
  ];
62
69
  exports.FEATURE_DEFINITIONS = [
@@ -90,7 +97,7 @@ const GB = 1024 * 1024 * 1024;
90
97
  */
91
98
  exports.DEFAULT_PLAN_LIMITS = {
92
99
  free: {
93
- meters: { storageBytes: 1 * GB, aiJobs: 25, trackedTickers: 3, seats: 1 },
100
+ meters: { storageBytes: 1 * GB, aiJobs: 25, trackedTickers: 3, seats: 1, assistantSpend: 5_000 },
94
101
  features: { cleanExport: false },
95
102
  retentionDays: 90
96
103
  },
@@ -107,7 +114,7 @@ exports.DEFAULT_PLAN_LIMITS = {
107
114
  * covering.
108
115
  */
109
116
  support: {
110
- meters: { storageBytes: 50 * GB, aiJobs: 600, trackedTickers: 100, seats: 5 },
117
+ meters: { storageBytes: 50 * GB, aiJobs: 600, trackedTickers: 100, seats: 5, assistantSpend: 20_000 },
111
118
  features: { cleanExport: true },
112
119
  retentionDays: exports.UNLIMITED
113
120
  },
@@ -122,7 +129,13 @@ exports.DEFAULT_PLAN_LIMITS = {
122
129
  * Kept off the public catalog through `Plan.isPublic = false`.
123
130
  */
124
131
  staff: {
125
- meters: { storageBytes: exports.UNLIMITED, aiJobs: exports.UNLIMITED, trackedTickers: exports.UNLIMITED, seats: exports.UNLIMITED },
132
+ meters: {
133
+ storageBytes: exports.UNLIMITED,
134
+ aiJobs: exports.UNLIMITED,
135
+ trackedTickers: exports.UNLIMITED,
136
+ seats: exports.UNLIMITED,
137
+ assistantSpend: exports.UNLIMITED
138
+ },
126
139
  features: { cleanExport: true },
127
140
  retentionDays: exports.UNLIMITED
128
141
  }
@@ -1 +1 @@
1
- {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/entitlements/definitions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/entitlements/definitions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /** Whether `groupId` is one of the groups the person belongs to. */
2
+ export declare const isMemberOf: (groupId: string, userGroups: readonly string[] | null | undefined) => boolean;
3
+ /**
4
+ * The one rule that keeps a group's data inside the group: a `groupId` that
5
+ * arrives in a request is never trusted, it must be one of the caller's own.
6
+ *
7
+ * No group named means the caller's personal data, which is always theirs, so
8
+ * `undefined` and `null` pass. A group they are not in throws a 403, never
9
+ * falls back to personal: reading someone else's group as "personal" would
10
+ * quietly show them nothing, and writing to it would not.
11
+ */
12
+ export declare function assertMemberOf(groupId: string | null | undefined, userGroups: readonly string[] | null | undefined, message?: string): void;
13
+ //# sourceMappingURL=access.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access.d.ts","sourceRoot":"","sources":["../../src/groups/access.ts"],"names":[],"mappings":"AAEA,oEAAoE;AACpE,eAAO,MAAM,UAAU,GAAI,SAAS,MAAM,EAAE,YAAY,SAAS,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,KAAG,OACvD,CAAC;AAEzC;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAClC,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,EAChD,OAAO,SAAkB,GACxB,IAAI,CAEN"}
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isMemberOf = void 0;
4
+ exports.assertMemberOf = assertMemberOf;
5
+ const HttpError_1 = require("../errors/HttpError");
6
+ /** Whether `groupId` is one of the groups the person belongs to. */
7
+ const isMemberOf = (groupId, userGroups) => Boolean(userGroups?.includes(groupId));
8
+ exports.isMemberOf = isMemberOf;
9
+ /**
10
+ * The one rule that keeps a group's data inside the group: a `groupId` that
11
+ * arrives in a request is never trusted, it must be one of the caller's own.
12
+ *
13
+ * No group named means the caller's personal data, which is always theirs, so
14
+ * `undefined` and `null` pass. A group they are not in throws a 403, never
15
+ * falls back to personal: reading someone else's group as "personal" would
16
+ * quietly show them nothing, and writing to it would not.
17
+ */
18
+ function assertMemberOf(groupId, userGroups, message = 'Access denied') {
19
+ if (groupId && !(0, exports.isMemberOf)(groupId, userGroups))
20
+ throw new HttpError_1.ForbiddenError(message);
21
+ }
22
+ //# sourceMappingURL=access.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access.js","sourceRoot":"","sources":["../../src/groups/access.ts"],"names":[],"mappings":";;;AAeA,wCAMC;AArBD,mDAAqD;AAErD,oEAAoE;AAC7D,MAAM,UAAU,GAAG,CAAC,OAAe,EAAE,UAAgD,EAAW,EAAE,CACvG,OAAO,CAAC,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;AAD5B,QAAA,UAAU,cACkB;AAEzC;;;;;;;;GAQG;AACH,SAAgB,cAAc,CAC5B,OAAkC,EAClC,UAAgD,EAChD,OAAO,GAAG,eAAe;IAEzB,IAAI,OAAO,IAAI,CAAC,IAAA,kBAAU,EAAC,OAAO,EAAE,UAAU,CAAC;QAAE,MAAM,IAAI,0BAAc,CAAC,OAAO,CAAC,CAAC;AACrF,CAAC"}
@@ -3,4 +3,5 @@ export type { GroupOwner } from './client';
3
3
  export { groupOwnerSubject } from './subject';
4
4
  export type { GroupIdResolver } from './subject';
5
5
  export { getUserGroupIds, currentGroupsOf, clearMembershipCache } from './membership';
6
+ export { assertMemberOf, isMemberOf } from './access';
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/groups/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AACrF,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,YAAY,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/groups/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AACrF,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,YAAY,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACtF,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.clearMembershipCache = exports.currentGroupsOf = exports.getUserGroupIds = exports.groupOwnerSubject = exports.clearGroupOwnerCache = exports.invalidateGroupOwner = exports.getGroupOwner = void 0;
3
+ exports.isMemberOf = exports.assertMemberOf = exports.clearMembershipCache = exports.currentGroupsOf = exports.getUserGroupIds = exports.groupOwnerSubject = exports.clearGroupOwnerCache = exports.invalidateGroupOwner = exports.getGroupOwner = void 0;
4
4
  var client_1 = require("./client");
5
5
  Object.defineProperty(exports, "getGroupOwner", { enumerable: true, get: function () { return client_1.getGroupOwner; } });
6
6
  Object.defineProperty(exports, "invalidateGroupOwner", { enumerable: true, get: function () { return client_1.invalidateGroupOwner; } });
@@ -11,4 +11,7 @@ var membership_1 = require("./membership");
11
11
  Object.defineProperty(exports, "getUserGroupIds", { enumerable: true, get: function () { return membership_1.getUserGroupIds; } });
12
12
  Object.defineProperty(exports, "currentGroupsOf", { enumerable: true, get: function () { return membership_1.currentGroupsOf; } });
13
13
  Object.defineProperty(exports, "clearMembershipCache", { enumerable: true, get: function () { return membership_1.clearMembershipCache; } });
14
+ var access_1 = require("./access");
15
+ Object.defineProperty(exports, "assertMemberOf", { enumerable: true, get: function () { return access_1.assertMemberOf; } });
16
+ Object.defineProperty(exports, "isMemberOf", { enumerable: true, get: function () { return access_1.isMemberOf; } });
14
17
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/groups/index.ts"],"names":[],"mappings":";;;AAAA,mCAAqF;AAA5E,uGAAA,aAAa,OAAA;AAAE,8GAAA,oBAAoB,OAAA;AAAE,8GAAA,oBAAoB,OAAA;AAGlE,qCAA8C;AAArC,4GAAA,iBAAiB,OAAA;AAG1B,2CAAsF;AAA7E,6GAAA,eAAe,OAAA;AAAE,6GAAA,eAAe,OAAA;AAAE,kHAAA,oBAAoB,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/groups/index.ts"],"names":[],"mappings":";;;AAAA,mCAAqF;AAA5E,uGAAA,aAAa,OAAA;AAAE,8GAAA,oBAAoB,OAAA;AAAE,8GAAA,oBAAoB,OAAA;AAGlE,qCAA8C;AAArC,4GAAA,iBAAiB,OAAA;AAG1B,2CAAsF;AAA7E,6GAAA,eAAe,OAAA;AAAE,6GAAA,eAAe,OAAA;AAAE,kHAAA,oBAAoB,OAAA;AAC/D,mCAAsD;AAA7C,wGAAA,cAAc,OAAA;AAAE,oGAAA,UAAU,OAAA"}
@@ -0,0 +1,34 @@
1
+ import { type Application } from 'express';
2
+ /** Makes every `use()` remember its path on the layers it adds. Idempotent. */
3
+ export declare function recordMountPaths(): void;
4
+ export interface Endpoint {
5
+ method: string;
6
+ /** In OpenAPI form: `/api/things/{id}`. */
7
+ path: string;
8
+ }
9
+ /** Every method and path the app answers, as OpenAPI would write them. */
10
+ export declare function listRoutes(app: Application): Endpoint[];
11
+ /**
12
+ * Every method and path a spec documents. A path item may live in a file of its
13
+ * own (`$ref: 'paths/thing.yml'`), as file-service's source spec does, so a
14
+ * relative `$ref` is followed.
15
+ */
16
+ export declare function listDocumented(specFile: string): Endpoint[];
17
+ /**
18
+ * Served by backend-core in every service, for the platform rather than for API
19
+ * callers: Kubernetes-style liveness and Prometheus. Not expected in each spec.
20
+ */
21
+ export declare const PLATFORM_ROUTES: string[];
22
+ export interface OpenApiDrift {
23
+ /** Routes the app serves that the spec does not mention. */
24
+ undocumented: string[];
25
+ /** Operations the spec describes that the app does not serve. */
26
+ stale: string[];
27
+ }
28
+ /**
29
+ * What the spec and the app disagree on. `ignore` takes routes that are
30
+ * deliberately left out of the docs (`'GET /docs'`, or a pattern), on top of
31
+ * the platform routes.
32
+ */
33
+ export declare function openApiDrift(app: Application, specFile: string, ignore?: Array<string | RegExp>): OpenApiDrift;
34
+ //# sourceMappingURL=openapi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openapi.d.ts","sourceRoot":"","sources":["../../src/testing/openapi.ts"],"names":[],"mappings":"AAEA,OAAgB,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAyBpD,+EAA+E;AAC/E,wBAAgB,gBAAgB,IAAI,IAAI,CAavC;AAED,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;CACd;AAYD,0EAA0E;AAC1E,wBAAgB,UAAU,CAAC,GAAG,EAAE,WAAW,GAAG,QAAQ,EAAE,CAsBvD;AAID;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,EAAE,CAY3D;AAMD;;;GAGG;AACH,eAAO,MAAM,eAAe,UAAuC,CAAC;AAEpE,MAAM,WAAW,YAAY;IAC3B,4DAA4D;IAC5D,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,iEAAiE;IACjE,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAM,GAAG,YAAY,CAalH"}
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.PLATFORM_ROUTES = void 0;
7
+ exports.recordMountPaths = recordMountPaths;
8
+ exports.listRoutes = listRoutes;
9
+ exports.listDocumented = listDocumented;
10
+ exports.openApiDrift = openApiDrift;
11
+ const fs_1 = __importDefault(require("fs"));
12
+ const path_1 = __importDefault(require("path"));
13
+ const express_1 = __importDefault(require("express"));
14
+ const yaml_1 = require("yaml");
15
+ let recording = false;
16
+ /** Makes every `use()` remember its path on the layers it adds. Idempotent. */
17
+ function recordMountPaths() {
18
+ if (recording)
19
+ return;
20
+ recording = true;
21
+ const proto = express_1.default.Router.prototype;
22
+ const use = proto.use;
23
+ proto.use = function (...args) {
24
+ const before = this.stack.length;
25
+ const result = use.apply(this, args);
26
+ const first = args[0];
27
+ const mountPath = typeof first === 'string' || Array.isArray(first) ? first : '/';
28
+ for (const layer of this.stack.slice(before))
29
+ layer.mountPath = mountPath;
30
+ return result;
31
+ };
32
+ }
33
+ const METHODS = ['get', 'post', 'put', 'patch', 'delete'];
34
+ const join = (prefix, path) => {
35
+ const joined = `${prefix}/${path}`.replace(/\/+/g, '/');
36
+ return joined.length > 1 ? joined.replace(/\/$/, '') : joined;
37
+ };
38
+ /** `/:id` and Express 5's `/*fileId` as OpenAPI writes them: `/{id}`, `/{fileId}`. */
39
+ const toOpenApiPath = (path) => path.replace(/[:*](\w+)/g, '{$1}');
40
+ /** Every method and path the app answers, as OpenAPI would write them. */
41
+ function listRoutes(app) {
42
+ const router = app.router ?? app._router;
43
+ if (!router)
44
+ throw new Error('The app has no router yet: build it before listing its routes');
45
+ const found = [];
46
+ const walk = (stack, prefix) => {
47
+ for (const layer of stack) {
48
+ if (layer.route) {
49
+ const paths = Array.isArray(layer.route.path) ? layer.route.path : [layer.route.path];
50
+ for (const path of paths) {
51
+ for (const method of Object.keys(layer.route.methods).filter((m) => METHODS.includes(m))) {
52
+ found.push({ method, path: toOpenApiPath(join(prefix, path)) });
53
+ }
54
+ }
55
+ }
56
+ else if (layer.handle?.stack) {
57
+ const mounts = layer.mountPath === undefined ? ['/'] : [].concat(layer.mountPath);
58
+ for (const mount of mounts)
59
+ walk(layer.handle.stack, join(prefix, mount));
60
+ }
61
+ }
62
+ };
63
+ walk(router.stack, '/');
64
+ return found;
65
+ }
66
+ const readYaml = (file) => (0, yaml_1.parse)(fs_1.default.readFileSync(file, 'utf8'));
67
+ /**
68
+ * Every method and path a spec documents. A path item may live in a file of its
69
+ * own (`$ref: 'paths/thing.yml'`), as file-service's source spec does, so a
70
+ * relative `$ref` is followed.
71
+ */
72
+ function listDocumented(specFile) {
73
+ const spec = readYaml(specFile);
74
+ return Object.entries(spec.paths ?? {}).flatMap(([path, item]) => {
75
+ const ref = item?.$ref;
76
+ const operations = typeof ref === 'string' && !ref.startsWith('#')
77
+ ? readYaml(path_1.default.resolve(path_1.default.dirname(specFile), ref))
78
+ : item;
79
+ return Object.keys(operations ?? {})
80
+ .filter((method) => METHODS.includes(method))
81
+ .map((method) => ({ method, path }));
82
+ });
83
+ }
84
+ /** A route's identity regardless of what its parameters are called: `{id}` and `{conversationId}` match. */
85
+ const key = ({ method, path }) => `${method.toUpperCase()} ${path.replace(/\{[^}]+\}/g, '{}')}`;
86
+ const label = ({ method, path }) => `${method.toUpperCase()} ${path}`;
87
+ /**
88
+ * Served by backend-core in every service, for the platform rather than for API
89
+ * callers: Kubernetes-style liveness and Prometheus. Not expected in each spec.
90
+ */
91
+ exports.PLATFORM_ROUTES = ['GET /health/live', 'GET /metrics'];
92
+ /**
93
+ * What the spec and the app disagree on. `ignore` takes routes that are
94
+ * deliberately left out of the docs (`'GET /docs'`, or a pattern), on top of
95
+ * the platform routes.
96
+ */
97
+ function openApiDrift(app, specFile, ignore = []) {
98
+ const rules = [...exports.PLATFORM_ROUTES, ...ignore];
99
+ const skipped = (endpoint) => rules.some((rule) => (typeof rule === 'string' ? rule === label(endpoint) : rule.test(label(endpoint))));
100
+ const routes = listRoutes(app).filter((endpoint) => !skipped(endpoint));
101
+ const documented = listDocumented(specFile).filter((endpoint) => !skipped(endpoint));
102
+ const routeKeys = new Set(routes.map(key));
103
+ const documentedKeys = new Set(documented.map(key));
104
+ const unique = (labels) => [...new Set(labels)].sort();
105
+ return {
106
+ undocumented: unique(routes.filter((endpoint) => !documentedKeys.has(key(endpoint))).map(label)),
107
+ stale: unique(documented.filter((endpoint) => !routeKeys.has(key(endpoint))).map(label))
108
+ };
109
+ }
110
+ //# sourceMappingURL=openapi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openapi.js","sourceRoot":"","sources":["../../src/testing/openapi.ts"],"names":[],"mappings":";;;;;;AA4BA,4CAaC;AAmBD,gCAsBC;AASD,wCAYC;AAwBD,oCAaC;AA5ID,4CAAoB;AACpB,gDAA4B;AAC5B,sDAAoD;AACpD,+BAA6B;AAsB7B,IAAI,SAAS,GAAG,KAAK,CAAC;AAEtB,+EAA+E;AAC/E,SAAgB,gBAAgB;IAC9B,IAAI,SAAS;QAAE,OAAO;IACtB,SAAS,GAAG,IAAI,CAAC;IACjB,MAAM,KAAK,GAAI,iBAAO,CAAC,MAA6E,CAAC,SAAS,CAAC;IAC/G,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;IACtB,KAAK,CAAC,GAAG,GAAG,UAAyB,GAAG,IAAe;QACrD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;QACjC,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACrC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,SAAS,GAAG,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAE,KAA2B,CAAC,CAAC,CAAC,GAAG,CAAC;QACzG,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;YAAE,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC;QAC1E,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC;AAQD,MAAM,OAAO,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;AAE1D,MAAM,IAAI,GAAG,CAAC,MAAc,EAAE,IAAY,EAAU,EAAE;IACpD,MAAM,MAAM,GAAG,GAAG,MAAM,IAAI,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACxD,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;AAChE,CAAC,CAAC;AAEF,sFAAsF;AACtF,MAAM,aAAa,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;AAEnF,0EAA0E;AAC1E,SAAgB,UAAU,CAAC,GAAgB;IACzC,MAAM,MAAM,GAAI,GAA0D,CAAC,MAAM,IAAK,GAAuC,CAAC,OAAO,CAAC;IACtI,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;IAC9F,MAAM,KAAK,GAAe,EAAE,CAAC;IAE7B,MAAM,IAAI,GAAG,CAAC,KAAc,EAAE,MAAc,EAAE,EAAE;QAC9C,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;YAC1B,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;gBAChB,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBACtF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;oBACzB,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;wBACzF,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;oBAClE,CAAC;gBACH,CAAC;YACH,CAAC;iBAAM,IAAI,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC;gBAC/B,MAAM,MAAM,GAAG,KAAK,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,EAAe,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;gBAChG,KAAK,MAAM,KAAK,IAAI,MAAM;oBAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;YAC5E,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IACF,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACxB,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAW,EAAE,CAAC,IAAA,YAAK,EAAC,YAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;AAEjF;;;;GAIG;AACH,SAAgB,cAAc,CAAC,QAAgB;IAC7C,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAwD,CAAC;IACvF,OAAO,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE;QAC/D,MAAM,GAAG,GAAG,IAAI,EAAE,IAAI,CAAC;QACvB,MAAM,UAAU,GACd,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC;YAC7C,CAAC,CAAE,QAAQ,CAAC,cAAQ,CAAC,OAAO,CAAC,cAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,CAA6B;YAC1F,CAAC,CAAC,IAAI,CAAC;QACX,OAAO,MAAM,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC;aACjC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;aAC5C,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,4GAA4G;AAC5G,MAAM,GAAG,GAAG,CAAC,EAAE,MAAM,EAAE,IAAI,EAAY,EAAE,EAAE,CAAC,GAAG,MAAM,CAAC,WAAW,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,EAAE,CAAC;AAC1G,MAAM,KAAK,GAAG,CAAC,EAAE,MAAM,EAAE,IAAI,EAAY,EAAE,EAAE,CAAC,GAAG,MAAM,CAAC,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC;AAEhF;;;GAGG;AACU,QAAA,eAAe,GAAG,CAAC,kBAAkB,EAAE,cAAc,CAAC,CAAC;AASpE;;;;GAIG;AACH,SAAgB,YAAY,CAAC,GAAgB,EAAE,QAAgB,EAAE,SAAiC,EAAE;IAClG,MAAM,KAAK,GAAG,CAAC,GAAG,uBAAe,EAAE,GAAG,MAAM,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,CAAC,QAAkB,EAAE,EAAE,CACrC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3G,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IACxE,MAAM,UAAU,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IACrF,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3C,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IACpD,MAAM,MAAM,GAAG,CAAC,MAAgB,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACjE,OAAO;QACL,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAChG,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;KACzF,CAAC;AACJ,CAAC"}
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const session_1 = require("../auth/session");
4
4
  const membership_1 = require("../groups/membership");
5
+ const openapi_1 = require("./openapi");
5
6
  /**
6
7
  * Jest setup for service test suites: they sign session tokens without a
7
8
  * session and run with no database or group-service, so every token's session
@@ -15,4 +16,6 @@ const membership_1 = require("../groups/membership");
15
16
  // No group-service either: a test token's own `groups` claim is taken as the
16
17
  // person's membership. The live lookup is tested in groups/membership.test.ts.
17
18
  (0, membership_1.overrideMembershipLookupForTests)(async (user) => user.groups ?? []);
19
+ // Before any app is built, so the OpenAPI drift check can see where routers are mounted.
20
+ (0, openapi_1.recordMountPaths)();
18
21
  //# sourceMappingURL=serviceTestSetup.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"serviceTestSetup.js","sourceRoot":"","sources":["../../src/testing/serviceTestSetup.ts"],"names":[],"mappings":";;AAAA,6CAA+D;AAC/D,qDAAwE;AAExE;;;;;;;;GAQG;AACH,IAAA,sCAA4B,EAAC,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC;AAE/C,6EAA6E;AAC7E,+EAA+E;AAC/E,IAAA,6CAAgC,EAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC"}
1
+ {"version":3,"file":"serviceTestSetup.js","sourceRoot":"","sources":["../../src/testing/serviceTestSetup.ts"],"names":[],"mappings":";;AAAA,6CAA+D;AAC/D,qDAAwE;AACxE,uCAA6C;AAE7C;;;;;;;;GAQG;AACH,IAAA,sCAA4B,EAAC,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC;AAE/C,6EAA6E;AAC7E,+EAA+E;AAC/E,IAAA,6CAAgC,EAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;AAEpE,yFAAyF;AACzF,IAAA,0BAAgB,GAAE,CAAC"}
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@tumbaland/backend-core",
3
- "version": "1.50.0",
3
+ "version": "1.52.0",
4
4
  "description": "Core shared functionality for Tumbaland backend services",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "files": [
8
8
  "dist",
9
- "testing.js"
9
+ "testing.js",
10
+ "testing.d.ts"
10
11
  ],
11
12
  "scripts": {
12
13
  "build": "tsc -p tsconfig.build.json",
@@ -60,6 +61,7 @@
60
61
  "prom-client": "^15.1.3",
61
62
  "uuid": "^14.0.3",
62
63
  "winston": "^3.19.0",
64
+ "yaml": "^2.9.1",
63
65
  "zod": "^4.6.7"
64
66
  },
65
67
  "peerDependencies": {
package/testing.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './dist/testing/openapi';
package/testing.js CHANGED
@@ -8,3 +8,6 @@
8
8
  * The session check itself is tested in backend-core (src/auth/session.test.ts).
9
9
  */
10
10
  require('./dist/testing/serviceTestSetup');
11
+
12
+ // The OpenAPI drift check, for a service's docs test.
13
+ module.exports = require('./dist/testing/openapi');