@selvajs/server 0.2.0-beta.3 → 0.2.0-beta.4

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 (145) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +32 -0
  3. package/dist/compute/client-cache.d.ts.map +1 -1
  4. package/dist/compute/client-cache.js +6 -0
  5. package/dist/compute/client-cache.js.map +1 -1
  6. package/dist/compute/safe-url.d.ts.map +1 -1
  7. package/dist/compute/safe-url.js +16 -0
  8. package/dist/compute/safe-url.js.map +1 -1
  9. package/dist/compute/solve-cache-single-flight.d.ts +8 -1
  10. package/dist/compute/solve-cache-single-flight.d.ts.map +1 -1
  11. package/dist/compute/solve-cache-single-flight.js +4 -2
  12. package/dist/compute/solve-cache-single-flight.js.map +1 -1
  13. package/dist/compute/solve-pipeline.d.ts.map +1 -1
  14. package/dist/compute/solve-pipeline.js +3 -1
  15. package/dist/compute/solve-pipeline.js.map +1 -1
  16. package/package.json +14 -18
  17. package/dist/access/__tests__/project-access-input.test.d.ts +0 -2
  18. package/dist/access/__tests__/project-access-input.test.d.ts.map +0 -1
  19. package/dist/access/__tests__/project-access-input.test.js +0 -146
  20. package/dist/access/__tests__/project-access-input.test.js.map +0 -1
  21. package/dist/compute/__tests__/client-cache.test.d.ts +0 -11
  22. package/dist/compute/__tests__/client-cache.test.d.ts.map +0 -1
  23. package/dist/compute/__tests__/client-cache.test.js +0 -218
  24. package/dist/compute/__tests__/client-cache.test.js.map +0 -1
  25. package/dist/compute/__tests__/definition-byte-cache.test.d.ts +0 -2
  26. package/dist/compute/__tests__/definition-byte-cache.test.d.ts.map +0 -1
  27. package/dist/compute/__tests__/definition-byte-cache.test.js +0 -107
  28. package/dist/compute/__tests__/definition-byte-cache.test.js.map +0 -1
  29. package/dist/compute/__tests__/rate-limit.test.d.ts +0 -2
  30. package/dist/compute/__tests__/rate-limit.test.d.ts.map +0 -1
  31. package/dist/compute/__tests__/rate-limit.test.js +0 -98
  32. package/dist/compute/__tests__/rate-limit.test.js.map +0 -1
  33. package/dist/compute/__tests__/remote-definition.test.d.ts +0 -11
  34. package/dist/compute/__tests__/remote-definition.test.d.ts.map +0 -1
  35. package/dist/compute/__tests__/remote-definition.test.js +0 -114
  36. package/dist/compute/__tests__/remote-definition.test.js.map +0 -1
  37. package/dist/compute/__tests__/safe-url.test.d.ts +0 -2
  38. package/dist/compute/__tests__/safe-url.test.d.ts.map +0 -1
  39. package/dist/compute/__tests__/safe-url.test.js +0 -71
  40. package/dist/compute/__tests__/safe-url.test.js.map +0 -1
  41. package/dist/compute/__tests__/solve-cache.test.d.ts +0 -13
  42. package/dist/compute/__tests__/solve-cache.test.d.ts.map +0 -1
  43. package/dist/compute/__tests__/solve-cache.test.js +0 -234
  44. package/dist/compute/__tests__/solve-cache.test.js.map +0 -1
  45. package/dist/compute/__tests__/solve-pipeline.test.d.ts +0 -11
  46. package/dist/compute/__tests__/solve-pipeline.test.d.ts.map +0 -1
  47. package/dist/compute/__tests__/solve-pipeline.test.js +0 -557
  48. package/dist/compute/__tests__/solve-pipeline.test.js.map +0 -1
  49. package/dist/compute/__tests__/transform-input.test.d.ts +0 -14
  50. package/dist/compute/__tests__/transform-input.test.d.ts.map +0 -1
  51. package/dist/compute/__tests__/transform-input.test.js +0 -120
  52. package/dist/compute/__tests__/transform-input.test.js.map +0 -1
  53. package/dist/definitions/__tests__/definition-service.test.d.ts +0 -14
  54. package/dist/definitions/__tests__/definition-service.test.d.ts.map +0 -1
  55. package/dist/definitions/__tests__/definition-service.test.js +0 -95
  56. package/dist/definitions/__tests__/definition-service.test.js.map +0 -1
  57. package/dist/definitions/__tests__/load-for-render.test.d.ts +0 -8
  58. package/dist/definitions/__tests__/load-for-render.test.d.ts.map +0 -1
  59. package/dist/definitions/__tests__/load-for-render.test.js +0 -196
  60. package/dist/definitions/__tests__/load-for-render.test.js.map +0 -1
  61. package/dist/definitions/__tests__/schema-extraction.test.d.ts +0 -11
  62. package/dist/definitions/__tests__/schema-extraction.test.d.ts.map +0 -1
  63. package/dist/definitions/__tests__/schema-extraction.test.js +0 -115
  64. package/dist/definitions/__tests__/schema-extraction.test.js.map +0 -1
  65. package/dist/http/__tests__/body-size.test.d.ts +0 -2
  66. package/dist/http/__tests__/body-size.test.d.ts.map +0 -1
  67. package/dist/http/__tests__/body-size.test.js +0 -24
  68. package/dist/http/__tests__/body-size.test.js.map +0 -1
  69. package/dist/http/__tests__/route-classifier.test.d.ts +0 -2
  70. package/dist/http/__tests__/route-classifier.test.d.ts.map +0 -1
  71. package/dist/http/__tests__/route-classifier.test.js +0 -54
  72. package/dist/http/__tests__/route-classifier.test.js.map +0 -1
  73. package/dist/http/__tests__/safe-redirect.test.d.ts +0 -2
  74. package/dist/http/__tests__/safe-redirect.test.d.ts.map +0 -1
  75. package/dist/http/__tests__/safe-redirect.test.js +0 -44
  76. package/dist/http/__tests__/safe-redirect.test.js.map +0 -1
  77. package/dist/http/__tests__/security-headers.test.d.ts +0 -2
  78. package/dist/http/__tests__/security-headers.test.d.ts.map +0 -1
  79. package/dist/http/__tests__/security-headers.test.js +0 -24
  80. package/dist/http/__tests__/security-headers.test.js.map +0 -1
  81. package/dist/ops/__tests__/semver.test.d.ts +0 -2
  82. package/dist/ops/__tests__/semver.test.d.ts.map +0 -1
  83. package/dist/ops/__tests__/semver.test.js +0 -38
  84. package/dist/ops/__tests__/semver.test.js.map +0 -1
  85. package/dist/providers/__tests__/create-selva-providers.test.d.ts +0 -7
  86. package/dist/providers/__tests__/create-selva-providers.test.d.ts.map +0 -1
  87. package/dist/providers/__tests__/create-selva-providers.test.js +0 -135
  88. package/dist/providers/__tests__/create-selva-providers.test.js.map +0 -1
  89. package/dist/tokens/__tests__/token-codec.test.d.ts +0 -2
  90. package/dist/tokens/__tests__/token-codec.test.d.ts.map +0 -1
  91. package/dist/tokens/__tests__/token-codec.test.js +0 -50
  92. package/dist/tokens/__tests__/token-codec.test.js.map +0 -1
  93. package/src/access/__tests__/project-access-input.test.ts +0 -175
  94. package/src/access/index.ts +0 -9
  95. package/src/access/project-access-input.ts +0 -145
  96. package/src/compute/__tests__/client-cache.test.ts +0 -244
  97. package/src/compute/__tests__/definition-byte-cache.test.ts +0 -129
  98. package/src/compute/__tests__/rate-limit.test.ts +0 -106
  99. package/src/compute/__tests__/remote-definition.test.ts +0 -140
  100. package/src/compute/__tests__/safe-url.test.ts +0 -72
  101. package/src/compute/__tests__/solve-cache.test.ts +0 -268
  102. package/src/compute/__tests__/solve-pipeline.test.ts +0 -660
  103. package/src/compute/__tests__/transform-input.test.ts +0 -162
  104. package/src/compute/client-cache.ts +0 -321
  105. package/src/compute/definition-byte-cache.ts +0 -168
  106. package/src/compute/index.ts +0 -82
  107. package/src/compute/limits.ts +0 -237
  108. package/src/compute/memory-solve-cache.ts +0 -0
  109. package/src/compute/rate-limit.ts +0 -110
  110. package/src/compute/remote-definition.ts +0 -149
  111. package/src/compute/safe-url.ts +0 -186
  112. package/src/compute/solve-cache-envelope.ts +0 -98
  113. package/src/compute/solve-cache-key.ts +0 -85
  114. package/src/compute/solve-cache-single-flight.ts +0 -59
  115. package/src/compute/solve-pipeline.ts +0 -603
  116. package/src/compute/transform-input.ts +0 -66
  117. package/src/definitions/__tests__/definition-service.test.ts +0 -131
  118. package/src/definitions/__tests__/load-for-render.test.ts +0 -244
  119. package/src/definitions/__tests__/schema-extraction.test.ts +0 -137
  120. package/src/definitions/definition-service.ts +0 -247
  121. package/src/definitions/index.ts +0 -22
  122. package/src/definitions/load-for-render.ts +0 -272
  123. package/src/definitions/schema-extraction.ts +0 -117
  124. package/src/errors/SentryErrorReporter.ts +0 -88
  125. package/src/errors/index.ts +0 -3
  126. package/src/http/__tests__/body-size.test.ts +0 -27
  127. package/src/http/__tests__/route-classifier.test.ts +0 -60
  128. package/src/http/__tests__/safe-redirect.test.ts +0 -47
  129. package/src/http/__tests__/security-headers.test.ts +0 -29
  130. package/src/http/body-size.ts +0 -24
  131. package/src/http/index.ts +0 -10
  132. package/src/http/redirect.ts +0 -16
  133. package/src/http/route-classifier.ts +0 -74
  134. package/src/http/security-headers.ts +0 -42
  135. package/src/index.ts +0 -27
  136. package/src/ops/__tests__/semver.test.ts +0 -42
  137. package/src/ops/index.ts +0 -3
  138. package/src/ops/semver.ts +0 -60
  139. package/src/providers/__tests__/create-selva-providers.test.ts +0 -172
  140. package/src/providers/__tests__/fixtures/override-config.mjs +0 -8
  141. package/src/providers/create-selva-providers.ts +0 -241
  142. package/src/providers/index.ts +0 -12
  143. package/src/tokens/__tests__/token-codec.test.ts +0 -63
  144. package/src/tokens/index.ts +0 -8
  145. package/src/tokens/token-codec.ts +0 -86
@@ -1,24 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { declaredBodySizeExceeds } from '../body-size.js';
3
- function headersWith(contentLength) {
4
- const h = new Headers();
5
- if (contentLength !== undefined)
6
- h.set('content-length', contentLength);
7
- return h;
8
- }
9
- describe('declaredBodySizeExceeds', () => {
10
- it('flags a declared size over the limit', () => {
11
- expect(declaredBodySizeExceeds(headersWith('1001'), 1000)).toBe(true);
12
- });
13
- it('passes a declared size at or under the limit', () => {
14
- expect(declaredBodySizeExceeds(headersWith('1000'), 1000)).toBe(false);
15
- expect(declaredBodySizeExceeds(headersWith('0'), 1000)).toBe(false);
16
- });
17
- it('passes when Content-Length is absent (chunked transfer — global limit is the backstop)', () => {
18
- expect(declaredBodySizeExceeds(headersWith(), 1000)).toBe(false);
19
- });
20
- it('passes a non-numeric Content-Length rather than throwing', () => {
21
- expect(declaredBodySizeExceeds(headersWith('not-a-number'), 1000)).toBe(false);
22
- });
23
- });
24
- //# sourceMappingURL=body-size.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"body-size.test.js","sourceRoot":"","sources":["../../../src/http/__tests__/body-size.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAE1D,SAAS,WAAW,CAAC,aAAsB;IAC1C,MAAM,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC;IACxB,IAAI,aAAa,KAAK,SAAS;QAAE,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAC;IACxE,OAAO,CAAC,CAAC;AACV,CAAC;AAED,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACxC,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC/C,MAAM,CAAC,uBAAuB,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACvD,MAAM,CAAC,uBAAuB,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,CAAC,uBAAuB,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wFAAwF,EAAE,GAAG,EAAE;QACjG,MAAM,CAAC,uBAAuB,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QACnE,MAAM,CAAC,uBAAuB,CAAC,WAAW,CAAC,cAAc,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChF,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=route-classifier.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"route-classifier.test.d.ts","sourceRoot":"","sources":["../../../src/http/__tests__/route-classifier.test.ts"],"names":[],"mappings":""}
@@ -1,54 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { createRouteClassifier } from '../route-classifier.js';
3
- // Generic values — the consuming app's actual route policy is pinned by its
4
- // own test suite; these cover the classifier mechanics.
5
- const classifier = createRouteClassifier({
6
- publicPages: ['/', '/login'],
7
- publicPrefixes: ['/auth/', '/logout'],
8
- publicApis: ['/api/health'],
9
- selfGatingPrefix: '/api/files/',
10
- staticPrefixes: ['/_app/', '/favicon/'],
11
- staticPaths: ['/favicon.svg', '/robots.txt']
12
- });
13
- describe('createRouteClassifier', () => {
14
- it('classifies exact pages, API allowlist, prefixes, and self-gating as public', () => {
15
- for (const path of [
16
- '/',
17
- '/login',
18
- '/api/health',
19
- '/auth/oauth/callback',
20
- '/logout',
21
- '/api/files/orgs/abc/logo.webp'
22
- ]) {
23
- expect(classifier.isPublicRoute(path)).toBe(true);
24
- }
25
- });
26
- it('denies by default — unknown routes are gated', () => {
27
- for (const path of ['/library', '/api/projects', '/billing', '/whatever']) {
28
- expect(classifier.isPublicRoute(path)).toBe(false);
29
- }
30
- });
31
- it('exact-match pages do not admit siblings via prefix', () => {
32
- expect(classifier.isPublicRoute('/login-other')).toBe(false);
33
- expect(classifier.isPublicRoute('/api/healthz')).toBe(false);
34
- });
35
- it('self-gating prefix is not a loose match', () => {
36
- expect(classifier.isSelfGatingApiRoute('/api/files/x')).toBe(true);
37
- expect(classifier.isSelfGatingApiRoute('/api/filesX/y')).toBe(false);
38
- expect(classifier.isSelfGatingApiRoute('/api/projects')).toBe(false);
39
- });
40
- it('recognizes static assets by prefix and exact path', () => {
41
- expect(classifier.isStaticAsset('/_app/immutable/x.js')).toBe(true);
42
- expect(classifier.isStaticAsset('/favicon/16.png')).toBe(true);
43
- expect(classifier.isStaticAsset('/robots.txt')).toBe(true);
44
- expect(classifier.isStaticAsset('/favicon-other.png')).toBe(false);
45
- expect(classifier.isStaticAsset('/login')).toBe(false);
46
- });
47
- it('every allowlist is optional — an empty config gates everything', () => {
48
- const closed = createRouteClassifier({});
49
- expect(closed.isPublicRoute('/')).toBe(false);
50
- expect(closed.isStaticAsset('/robots.txt')).toBe(false);
51
- expect(closed.isSelfGatingApiRoute('/api/files/x')).toBe(false);
52
- });
53
- });
54
- //# sourceMappingURL=route-classifier.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"route-classifier.test.js","sourceRoot":"","sources":["../../../src/http/__tests__/route-classifier.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,4EAA4E;AAC5E,wDAAwD;AACxD,MAAM,UAAU,GAAG,qBAAqB,CAAC;IACxC,WAAW,EAAE,CAAC,GAAG,EAAE,QAAQ,CAAC;IAC5B,cAAc,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC;IACrC,UAAU,EAAE,CAAC,aAAa,CAAC;IAC3B,gBAAgB,EAAE,aAAa;IAC/B,cAAc,EAAE,CAAC,QAAQ,EAAE,WAAW,CAAC;IACvC,WAAW,EAAE,CAAC,cAAc,EAAE,aAAa,CAAC;CAC5C,CAAC,CAAC;AAEH,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACtC,EAAE,CAAC,4EAA4E,EAAE,GAAG,EAAE;QACrF,KAAK,MAAM,IAAI,IAAI;YAClB,GAAG;YACH,QAAQ;YACR,aAAa;YACb,sBAAsB;YACtB,SAAS;YACT,+BAA+B;SAC/B,EAAE,CAAC;YACH,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnD,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACvD,KAAK,MAAM,IAAI,IAAI,CAAC,UAAU,EAAE,eAAe,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,CAAC;YAC3E,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpD,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC7D,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7D,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QAClD,MAAM,CAAC,UAAU,CAAC,oBAAoB,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnE,MAAM,CAAC,UAAU,CAAC,oBAAoB,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrE,MAAM,CAAC,UAAU,CAAC,oBAAoB,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC5D,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,sBAAsB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpE,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/D,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3D,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnE,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACzE,MAAM,MAAM,GAAG,qBAAqB,CAAC,EAAE,CAAC,CAAC;QACzC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9C,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxD,MAAM,CAAC,MAAM,CAAC,oBAAoB,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=safe-redirect.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"safe-redirect.test.d.ts","sourceRoot":"","sources":["../../../src/http/__tests__/safe-redirect.test.ts"],"names":[],"mappings":""}
@@ -1,44 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { safeRedirectTarget } from '../redirect.js';
3
- /**
4
- * `safeRedirectTarget` is the post-login redirect validator. The point of
5
- * the function is to reject *exactly* the values that would otherwise
6
- * smuggle an external host into a `redirect(303, …)` call:
7
- * protocol-relative URLs (`//evil.com`) and back-slash variants some
8
- * browsers normalize as a path separator. Each row below is one such case.
9
- */
10
- describe('safeRedirectTarget', () => {
11
- it.each([
12
- ['/foo', '/foo'],
13
- ['/foo/bar', '/foo/bar'],
14
- ['/foo?x=1', '/foo?x=1'],
15
- ['/foo#frag', '/foo#frag'],
16
- ['/a', '/a'] // shortest valid path: `/` + non-`/` char
17
- ])('accepts same-origin path %j → %j', (input, expected) => {
18
- expect(safeRedirectTarget(input, '/fallback')).toBe(expected);
19
- });
20
- it.each([
21
- ['//evil.com', 'protocol-relative URL'],
22
- ['//evil.com/path', 'protocol-relative URL with path'],
23
- ['/\\evil.com', 'back-slash bypass'],
24
- ['https://evil.com', 'absolute URL'],
25
- ['http://evil.com', 'absolute URL'],
26
- ['javascript:alert(1)', 'javascript: scheme'],
27
- ['', 'empty string'],
28
- ['/', 'lone slash (length<2)'],
29
- ['evil.com', 'no leading slash'],
30
- ['./relative', 'relative path']
31
- ])('rejects %j (%s)', (input) => {
32
- expect(safeRedirectTarget(input, '/fallback')).toBe('/fallback');
33
- });
34
- it.each([null, undefined])('rejects %j', (input) => {
35
- expect(safeRedirectTarget(input, '/fallback')).toBe('/fallback');
36
- });
37
- it('passes through arbitrary non-string types as fallback', () => {
38
- // safeRedirectTarget's signature is `string | null | undefined`, but
39
- // some call sites get `unknown` from FormData — make sure we don't
40
- // throw on a stray non-string.
41
- expect(safeRedirectTarget(42, '/fallback')).toBe('/fallback');
42
- });
43
- });
44
- //# sourceMappingURL=safe-redirect.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"safe-redirect.test.js","sourceRoot":"","sources":["../../../src/http/__tests__/safe-redirect.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEpD;;;;;;GAMG;AACH,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IACnC,EAAE,CAAC,IAAI,CAAC;QACP,CAAC,MAAM,EAAE,MAAM,CAAC;QAChB,CAAC,UAAU,EAAE,UAAU,CAAC;QACxB,CAAC,UAAU,EAAE,UAAU,CAAC;QACxB,CAAC,WAAW,EAAE,WAAW,CAAC;QAC1B,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,0CAA0C;KACvD,CAAC,CAAC,kCAAkC,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;QAC1D,MAAM,CAAC,kBAAkB,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,IAAI,CAAC;QACP,CAAC,YAAY,EAAE,uBAAuB,CAAC;QACvC,CAAC,iBAAiB,EAAE,iCAAiC,CAAC;QACtD,CAAC,aAAa,EAAE,mBAAmB,CAAC;QACpC,CAAC,kBAAkB,EAAE,cAAc,CAAC;QACpC,CAAC,iBAAiB,EAAE,cAAc,CAAC;QACnC,CAAC,qBAAqB,EAAE,oBAAoB,CAAC;QAC7C,CAAC,EAAE,EAAE,cAAc,CAAC;QACpB,CAAC,GAAG,EAAE,uBAAuB,CAAC;QAC9B,CAAC,UAAU,EAAE,kBAAkB,CAAC;QAChC,CAAC,YAAY,EAAE,eAAe,CAAC;KAC/B,CAAC,CAAC,iBAAiB,EAAE,CAAC,KAAK,EAAE,EAAE;QAC/B,MAAM,CAAC,kBAAkB,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,KAAK,EAAE,EAAE;QAClD,MAAM,CAAC,kBAAkB,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAChE,qEAAqE;QACrE,mEAAmE;QACnE,+BAA+B;QAC/B,MAAM,CAAC,kBAAkB,CAAC,EAAuB,EAAE,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACpF,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=security-headers.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"security-headers.test.d.ts","sourceRoot":"","sources":["../../../src/http/__tests__/security-headers.test.ts"],"names":[],"mappings":""}
@@ -1,24 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { applySecurityHeaders } from '../security-headers.js';
3
- describe('applySecurityHeaders', () => {
4
- it('sets the baseline hardening headers and returns the same response', () => {
5
- const response = new Response('ok');
6
- const out = applySecurityHeaders(response, { hsts: false });
7
- expect(out).toBe(response);
8
- expect(out.headers.get('X-Content-Type-Options')).toBe('nosniff');
9
- expect(out.headers.get('Referrer-Policy')).toBe('strict-origin-when-cross-origin');
10
- expect(out.headers.get('Permissions-Policy')).toContain('camera=()');
11
- });
12
- it('sets HSTS only when asked (production)', () => {
13
- const dev = applySecurityHeaders(new Response('ok'), { hsts: false });
14
- expect(dev.headers.get('Strict-Transport-Security')).toBeNull();
15
- const prod = applySecurityHeaders(new Response('ok'), { hsts: true });
16
- expect(prod.headers.get('Strict-Transport-Security')).toBe('max-age=31536000; includeSubDomains');
17
- });
18
- it('never sets CSP or frame headers (iframe embedding is a product requirement)', () => {
19
- const out = applySecurityHeaders(new Response('ok'), { hsts: true });
20
- expect(out.headers.get('Content-Security-Policy')).toBeNull();
21
- expect(out.headers.get('X-Frame-Options')).toBeNull();
22
- });
23
- });
24
- //# sourceMappingURL=security-headers.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"security-headers.test.js","sourceRoot":"","sources":["../../../src/http/__tests__/security-headers.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAE9D,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACrC,EAAE,CAAC,mEAAmE,EAAE,GAAG,EAAE;QAC5E,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,GAAG,GAAG,oBAAoB,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC5D,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3B,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAClE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;QACnF,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QACjD,MAAM,GAAG,GAAG,oBAAoB,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACtE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;QAEhE,MAAM,IAAI,GAAG,oBAAoB,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACtE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC,CAAC,IAAI,CACzD,qCAAqC,CACrC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,GAAG,EAAE;QACtF,MAAM,GAAG,GAAG,oBAAoB,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC9D,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACvD,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=semver.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"semver.test.d.ts","sourceRoot":"","sources":["../../../src/ops/__tests__/semver.test.ts"],"names":[],"mappings":""}
@@ -1,38 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { isNewer } from '../semver.js';
3
- describe('isNewer', () => {
4
- it('detects a newer patch / minor / major', () => {
5
- expect(isNewer('4.3.2', '4.3.1')).toBe(true);
6
- expect(isNewer('4.4.0', '4.3.9')).toBe(true);
7
- expect(isNewer('5.0.0', '4.9.9')).toBe(true);
8
- });
9
- it('returns false for same or older versions', () => {
10
- expect(isNewer('4.3.1', '4.3.1')).toBe(false);
11
- expect(isNewer('4.3.0', '4.3.1')).toBe(false);
12
- expect(isNewer('3.9.9', '4.0.0')).toBe(false);
13
- });
14
- it('ignores pre-release suffixes on the stable channel (only stable bumps surface)', () => {
15
- expect(isNewer('4.3.2-beta.1', '4.3.1')).toBe(true);
16
- expect(isNewer('4.3.1-beta.1', '4.3.1')).toBe(false);
17
- // Explicit stable channel matches the default.
18
- expect(isNewer('4.3.1-beta.1', '4.3.1', 'stable')).toBe(false);
19
- });
20
- it('orders pre-releases on the beta channel', () => {
21
- // Successive betas of the same core.
22
- expect(isNewer('4.6.0-beta.2', '4.6.0-beta.1', 'beta')).toBe(true);
23
- expect(isNewer('4.6.0-beta.1', '4.6.0-beta.2', 'beta')).toBe(false);
24
- // A newer core beta beats an older stable.
25
- expect(isNewer('4.6.0-beta.1', '4.5.1', 'beta')).toBe(true);
26
- // Stable of a core outranks any beta of the same core (promotion).
27
- expect(isNewer('4.6.0', '4.6.0-beta.9', 'beta')).toBe(true);
28
- expect(isNewer('4.6.0-beta.9', '4.6.0', 'beta')).toBe(false);
29
- // Reverting to an OLDER stable is NOT "newer" — the channel switch, not
30
- // isNewer, is what makes it actionable.
31
- expect(isNewer('4.5.1', '4.6.0-beta.2', 'beta')).toBe(false);
32
- });
33
- it('falls back to a string compare when unparseable', () => {
34
- expect(isNewer('weird', 'weird')).toBe(false);
35
- expect(isNewer('a', 'b')).toBe(true);
36
- });
37
- });
38
- //# sourceMappingURL=semver.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"semver.test.js","sourceRoot":"","sources":["../../../src/ops/__tests__/semver.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;IACxB,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAChD,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7C,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7C,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QACnD,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9C,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9C,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gFAAgF,EAAE,GAAG,EAAE;QACzF,MAAM,CAAC,OAAO,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpD,MAAM,CAAC,OAAO,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrD,+CAA+C;QAC/C,MAAM,CAAC,OAAO,CAAC,cAAc,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QAClD,qCAAqC;QACrC,MAAM,CAAC,OAAO,CAAC,cAAc,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnE,MAAM,CAAC,OAAO,CAAC,cAAc,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpE,2CAA2C;QAC3C,MAAM,CAAC,OAAO,CAAC,cAAc,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5D,mEAAmE;QACnE,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5D,MAAM,CAAC,OAAO,CAAC,cAAc,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7D,wEAAwE;QACxE,wCAAwC;QACxC,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QAC1D,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9C,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -1,7 +0,0 @@
1
- /**
2
- * Tests for `createSelvaProviders` (K5) — registry-driven provider selection,
3
- * lazy memoized instantiation, config parsing (flags/branding/tenancy), the
4
- * solve-metrics duck-type pick, and the external config-path override.
5
- */
6
- export {};
7
- //# sourceMappingURL=create-selva-providers.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"create-selva-providers.test.d.ts","sourceRoot":"","sources":["../../../src/providers/__tests__/create-selva-providers.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -1,135 +0,0 @@
1
- /**
2
- * Tests for `createSelvaProviders` (K5) — registry-driven provider selection,
3
- * lazy memoized instantiation, config parsing (flags/branding/tenancy), the
4
- * solve-metrics duck-type pick, and the external config-path override.
5
- */
6
- import { describe, it, expect, vi } from 'vitest';
7
- import { fileURLToPath } from 'node:url';
8
- import { createSelvaProviders } from '../create-selva-providers.js';
9
- class FakeData {
10
- }
11
- class FakeStorage {
12
- }
13
- function makeRegistry() {
14
- const authLocal = vi.fn(() => ({ name: 'local-auth' }));
15
- const authSupabase = vi.fn(() => ({ name: 'supabase-auth' }));
16
- const dataLocal = vi.fn(() => new FakeData());
17
- const dataSupabase = vi.fn(() => new FakeData());
18
- const storageLocal = vi.fn(() => new FakeStorage());
19
- const registry = {
20
- auth: { local: authLocal, supabase: authSupabase },
21
- data: { local: dataLocal, supabase: dataSupabase },
22
- storage: { local: storageLocal }
23
- };
24
- return { registry, authLocal, authSupabase, dataLocal, dataSupabase, storageLocal };
25
- }
26
- const noBoot = { onBoot: () => { } };
27
- describe('registry selection', () => {
28
- it('falls back to "local" for every slot when env is empty', async () => {
29
- const { registry, authLocal, dataLocal, storageLocal } = makeRegistry();
30
- const runtime = await createSelvaProviders({}, { registry, ...noBoot });
31
- runtime.resolve();
32
- expect(authLocal).toHaveBeenCalledTimes(1);
33
- expect(dataLocal).toHaveBeenCalledTimes(1);
34
- expect(storageLocal).toHaveBeenCalledTimes(1);
35
- });
36
- it('honors SELVA_*_PROVIDER env choices, case-insensitively', async () => {
37
- const { registry, authSupabase, dataSupabase } = makeRegistry();
38
- const runtime = await createSelvaProviders({ SELVA_AUTH_PROVIDER: 'Supabase', SELVA_DATA_PROVIDER: 'SUPABASE' }, { registry, ...noBoot });
39
- runtime.resolve();
40
- expect(authSupabase).toHaveBeenCalledTimes(1);
41
- expect(dataSupabase).toHaveBeenCalledTimes(1);
42
- });
43
- it('honors the defaults option over the built-in "local"', async () => {
44
- const { registry, authSupabase } = makeRegistry();
45
- const runtime = await createSelvaProviders({}, { registry, defaults: { auth: 'supabase' }, ...noBoot });
46
- runtime.resolve();
47
- expect(authSupabase).toHaveBeenCalledTimes(1);
48
- });
49
- it('rejects an unknown choice, listing the registered names', async () => {
50
- const { registry } = makeRegistry();
51
- const runtime = await createSelvaProviders({ SELVA_AUTH_PROVIDER: 'okta' }, { registry, ...noBoot });
52
- expect(() => runtime.resolve()).toThrow(/SELVA_AUTH_PROVIDER="okta".*local \| supabase/);
53
- });
54
- });
55
- describe('laziness and memoization', () => {
56
- it('does not instantiate providers until resolve() is called', async () => {
57
- const { registry, authLocal } = makeRegistry();
58
- await createSelvaProviders({}, { registry, ...noBoot });
59
- expect(authLocal).not.toHaveBeenCalled();
60
- });
61
- it('instantiates once and logs the boot summary once across repeated resolves', async () => {
62
- const { registry, authLocal } = makeRegistry();
63
- const onBoot = vi.fn();
64
- const runtime = await createSelvaProviders({}, { registry, onBoot });
65
- runtime.resolve();
66
- runtime.resolve();
67
- runtime.flag('ENABLE_SHARING');
68
- expect(authLocal).toHaveBeenCalledTimes(1);
69
- expect(onBoot).toHaveBeenCalledTimes(1);
70
- expect(onBoot.mock.calls[0][0]).toContain('auth=local-auth');
71
- expect(onBoot.mock.calls[0][0]).toContain('data=FakeData');
72
- expect(onBoot.mock.calls[0][0]).toContain('tenancy=single');
73
- });
74
- });
75
- describe('config parsing', () => {
76
- it('parses flags from SELVA_FLAG_* (omitted → false)', async () => {
77
- const { registry } = makeRegistry();
78
- const runtime = await createSelvaProviders({ SELVA_FLAG_ENABLE_SHARING: 'true', SELVA_FLAG_ALLOW_ORG_CREATION: 'no' }, { registry, ...noBoot });
79
- expect(runtime.flag('ENABLE_SHARING')).toBe(true);
80
- expect(runtime.flag('ALLOW_ORG_CREATION')).toBe(false);
81
- expect(runtime.flag('ALLOW_CROSS_ORG_PUBLIC')).toBe(false);
82
- });
83
- it('parses tenancy and rejects unknown values', async () => {
84
- const { registry } = makeRegistry();
85
- const multi = await createSelvaProviders({ SELVA_TENANCY: 'multi' }, { registry, ...noBoot });
86
- expect(multi.tenancy()).toBe('multi');
87
- const bad = await createSelvaProviders({ SELVA_TENANCY: 'galactic' }, { registry, ...noBoot });
88
- expect(() => bad.tenancy()).toThrow(/SELVA_TENANCY="galactic"/);
89
- });
90
- it('brands with defaults; copyright falls back to the overridden name', async () => {
91
- const { registry } = makeRegistry();
92
- const plain = await createSelvaProviders({}, { registry, ...noBoot });
93
- expect(plain.branding().name).toBe('Selva');
94
- expect(plain.branding().copyrightName).toBe('Selva');
95
- expect(plain.branding().tagline).toBeTruthy();
96
- const branded = await createSelvaProviders({ SELVA_BRAND_NAME: ' Acme ' }, { registry, ...noBoot });
97
- expect(branded.branding().name).toBe('Acme');
98
- expect(branded.branding().copyrightName).toBe('Acme');
99
- expect(branded.branding().description).toContain('Acme');
100
- });
101
- });
102
- describe('solve metric sink', () => {
103
- it('falls back to a noop sink when the data provider has no solveMetrics', async () => {
104
- const { registry } = makeRegistry();
105
- const runtime = await createSelvaProviders({}, { registry, ...noBoot });
106
- const sink = runtime.solveMetricSink();
107
- expect(typeof sink.record).toBe('function');
108
- expect(runtime.solveMetricSink()).toBe(sink); // memoized
109
- });
110
- it('reuses a duck-typed solveMetrics sink carried by the data provider', async () => {
111
- const { registry } = makeRegistry();
112
- const carried = { record: vi.fn() };
113
- registry.data.local = vi.fn(() => ({ solveMetrics: carried }));
114
- const runtime = await createSelvaProviders({}, { registry, ...noBoot });
115
- expect(runtime.solveMetricSink()).toBe(carried);
116
- });
117
- });
118
- describe('config-path override', () => {
119
- it('loads the module default export and hands it the env', async () => {
120
- const { registry, authLocal } = makeRegistry();
121
- const configPath = fileURLToPath(new URL('./fixtures/override-config.mjs', import.meta.url));
122
- const runtime = await createSelvaProviders({ OVERRIDE_MARKER: 'hello' }, { registry, configPath, ...noBoot });
123
- const config = runtime.resolve();
124
- expect(config.auth.name).toBe('override-auth');
125
- expect(config.data.marker).toBe('hello');
126
- expect(runtime.tenancy()).toBe('multi');
127
- // The registry is bypassed entirely.
128
- expect(authLocal).not.toHaveBeenCalled();
129
- });
130
- it('rejects at load time when the path does not exist', async () => {
131
- const { registry } = makeRegistry();
132
- await expect(createSelvaProviders({}, { registry, configPath: './does-not-exist.js', ...noBoot })).rejects.toThrow(/does-not-exist\.js/);
133
- });
134
- });
135
- //# sourceMappingURL=create-selva-providers.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"create-selva-providers.test.js","sourceRoot":"","sources":["../../../src/providers/__tests__/create-selva-providers.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=token-codec.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"token-codec.test.d.ts","sourceRoot":"","sources":["../../../src/tokens/__tests__/token-codec.test.ts"],"names":[],"mappings":""}
@@ -1,50 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { createTokenCodec, MIN_TOKEN_SECRET_LENGTH } from '../token-codec.js';
3
- const SECRET = 'unit-test-secret-that-is-long-enough-to-pass';
4
- describe('createTokenCodec', () => {
5
- it('rejects a secret shorter than the minimum', () => {
6
- expect(() => createTokenCodec({ prefix: 'share_', secret: 'short' })).toThrow(/at least 32 characters/);
7
- expect(() => createTokenCodec({ prefix: 'share_', secret: 'x'.repeat(MIN_TOKEN_SECRET_LENGTH - 1) })).toThrow(/got 31/);
8
- });
9
- it('accepts a secret at exactly the minimum length', () => {
10
- expect(() => createTokenCodec({ prefix: 'share_', secret: 'x'.repeat(MIN_TOKEN_SECRET_LENGTH) })).not.toThrow();
11
- });
12
- it('mints prefixed, unique, URL-safe tokens', () => {
13
- const codec = createTokenCodec({ prefix: 'share_', secret: SECRET });
14
- const a = codec.mintRawToken();
15
- const b = codec.mintRawToken();
16
- expect(a).toMatch(/^share_[A-Za-z0-9_-]{43}$/); // 32 bytes → 43 base64url chars
17
- expect(a).not.toBe(b);
18
- });
19
- it('hashes deterministically, never echoing the raw token', () => {
20
- const codec = createTokenCodec({ prefix: 'share_', secret: SECRET });
21
- const raw = codec.mintRawToken();
22
- const hash = codec.hashToken(raw);
23
- expect(codec.hashToken(raw)).toBe(hash);
24
- expect(hash).not.toContain(raw);
25
- expect(hash).toMatch(/^[A-Za-z0-9_-]+$/); // base64url
26
- });
27
- it('produces different hashes under different secrets (rotation invalidates)', () => {
28
- const a = createTokenCodec({ prefix: 'share_', secret: SECRET });
29
- const b = createTokenCodec({ prefix: 'share_', secret: SECRET + '-rotated' });
30
- const raw = a.mintRawToken();
31
- expect(a.hashToken(raw)).not.toBe(b.hashToken(raw));
32
- });
33
- it('hashesEqual: equal, unequal, and length-mismatch inputs', () => {
34
- const codec = createTokenCodec({ prefix: 'invite_', secret: SECRET });
35
- const hash = codec.hashToken(codec.mintRawToken());
36
- const other = codec.hashToken(codec.mintRawToken());
37
- expect(codec.hashesEqual(hash, hash)).toBe(true);
38
- expect(codec.hashesEqual(hash, other)).toBe(false);
39
- expect(codec.hashesEqual(hash, hash.slice(0, -1))).toBe(false);
40
- });
41
- it('looksLikeToken recognizes only its own prefix', () => {
42
- const share = createTokenCodec({ prefix: 'share_', secret: SECRET });
43
- const invite = createTokenCodec({ prefix: 'invite_', secret: SECRET });
44
- const raw = share.mintRawToken();
45
- expect(share.looksLikeToken(raw)).toBe(true);
46
- expect(invite.looksLikeToken(raw)).toBe(false);
47
- expect(share.looksLikeToken('random-string')).toBe(false);
48
- });
49
- });
50
- //# sourceMappingURL=token-codec.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"token-codec.test.js","sourceRoot":"","sources":["../../../src/tokens/__tests__/token-codec.test.ts"],"names":[],"mappings":"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"}