@selvajs/platform 0.21.0-beta.2 → 1.0.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.
- package/README.md +10 -7
- package/dist/access/index.d.ts +1 -2
- package/dist/access/index.js +1 -2
- package/dist/access/rules.d.ts +11 -12
- package/dist/access/rules.js +27 -23
- package/dist/apiTokens/index.d.ts +2 -3
- package/dist/apiTokens/index.js +2 -3
- package/dist/apiTokens/interface.d.ts +0 -1
- package/dist/apiTokens/interface.js +0 -1
- package/dist/apiTokens/scope.d.ts +3 -2
- package/dist/apiTokens/scope.js +9 -5
- package/dist/apiTokens/types.d.ts +7 -2
- package/dist/apiTokens/types.js +10 -5
- package/dist/auth/index.d.ts +0 -1
- package/dist/auth/index.js +0 -1
- package/dist/auth/interface.d.ts +4 -23
- package/dist/auth/interface.js +0 -1
- package/dist/auth/types.d.ts +4 -2
- package/dist/auth/types.js +0 -1
- package/dist/bindings/index.d.ts +0 -1
- package/dist/bindings/index.js +0 -1
- package/dist/bindings/interface.d.ts +0 -1
- package/dist/bindings/interface.js +0 -1
- package/dist/computeServer/index.d.ts +1 -7
- package/dist/computeServer/index.js +2 -8
- package/dist/computeServer/interface.d.ts +9 -6
- package/dist/computeServer/interface.js +0 -1
- package/dist/computeServer/public.d.ts +6 -0
- package/dist/computeServer/public.js +2 -0
- package/dist/computeServer/secrets.d.ts +12 -6
- package/dist/computeServer/secrets.js +35 -15
- package/dist/computeServer/types.d.ts +5 -2
- package/dist/computeServer/types.js +4 -1
- package/dist/computeServer/utils.d.ts +17 -6
- package/dist/computeServer/utils.js +31 -21
- package/dist/config.d.ts +1 -2
- package/dist/config.js +0 -1
- package/dist/context.d.ts +12 -1
- package/dist/context.js +51 -2
- package/dist/data/index.d.ts +0 -1
- package/dist/data/index.js +0 -1
- package/dist/data/interface.d.ts +0 -1
- package/dist/data/interface.js +0 -1
- package/dist/definitions/index.d.ts +2 -3
- package/dist/definitions/index.js +2 -3
- package/dist/definitions/interface.d.ts +0 -1
- package/dist/definitions/interface.js +0 -1
- package/dist/definitions/paths.d.ts +0 -1
- package/dist/definitions/paths.js +1 -12
- package/dist/definitions/schemas.d.ts +2 -21
- package/dist/definitions/schemas.js +10 -19
- package/dist/definitions/types.d.ts +12 -4
- package/dist/definitions/types.js +1 -3
- package/dist/errors/interface.d.ts +1 -2
- package/dist/errors/interface.js +0 -1
- package/dist/errors.d.ts +8 -1
- package/dist/errors.js +11 -1
- package/dist/events/audit.d.ts +1 -2
- package/dist/events/audit.js +0 -1
- package/dist/events/index.d.ts +0 -1
- package/dist/events/index.js +0 -1
- package/dist/events/interface.d.ts +0 -1
- package/dist/events/interface.js +0 -1
- package/dist/index.d.ts +18 -61
- package/dist/index.js +18 -24
- package/dist/invites/index.d.ts +0 -1
- package/dist/invites/index.js +0 -1
- package/dist/invites/interface.d.ts +5 -6
- package/dist/invites/interface.js +0 -1
- package/dist/invites/types.d.ts +0 -1
- package/dist/invites/types.js +0 -1
- package/dist/logging/interface.d.ts +0 -1
- package/dist/logging/interface.js +0 -1
- package/dist/metrics/interface.d.ts +0 -1
- package/dist/metrics/interface.js +0 -1
- package/dist/notifications/index.d.ts +0 -1
- package/dist/notifications/index.js +0 -1
- package/dist/notifications/interface.d.ts +1 -3
- package/dist/notifications/interface.js +1 -3
- package/dist/notifications/types.d.ts +0 -1
- package/dist/notifications/types.js +0 -1
- package/dist/organizations/index.d.ts +2 -3
- package/dist/organizations/index.js +1 -2
- package/dist/organizations/interface.d.ts +3 -5
- package/dist/organizations/interface.js +0 -1
- package/dist/organizations/paths.d.ts +1 -6
- package/dist/organizations/paths.js +2 -20
- package/dist/organizations/schemas.d.ts +5 -7
- package/dist/organizations/schemas.js +20 -13
- package/dist/organizations/types.d.ts +0 -1
- package/dist/organizations/types.js +0 -1
- package/dist/pagination.d.ts +11 -3
- package/dist/pagination.js +15 -1
- package/dist/permissions/index.d.ts +2 -2
- package/dist/permissions/index.js +2 -2
- package/dist/permissions/interface.d.ts +4 -4
- package/dist/permissions/interface.js +0 -1
- package/dist/permissions/types.d.ts +0 -1
- package/dist/permissions/types.js +0 -1
- package/dist/platformProjects/index.d.ts +1 -3
- package/dist/platformProjects/index.js +1 -2
- package/dist/platformProjects/interface.d.ts +0 -1
- package/dist/platformProjects/interface.js +0 -1
- package/dist/platformProjects/schemas.d.ts +0 -1
- package/dist/platformProjects/schemas.js +0 -1
- package/dist/platformProjects/types.d.ts +3 -2
- package/dist/platformProjects/types.js +0 -1
- package/dist/projects/index.d.ts +0 -1
- package/dist/projects/index.js +0 -1
- package/dist/projects/interface.d.ts +0 -1
- package/dist/projects/interface.js +0 -1
- package/dist/projects/schemas.d.ts +0 -1
- package/dist/projects/schemas.js +0 -1
- package/dist/projects/types.d.ts +0 -1
- package/dist/projects/types.js +0 -1
- package/dist/shareLinks/index.d.ts +0 -1
- package/dist/shareLinks/index.js +0 -1
- package/dist/shareLinks/interface.d.ts +6 -3
- package/dist/shareLinks/interface.js +0 -1
- package/dist/shareLinks/schemas.d.ts +0 -1
- package/dist/shareLinks/schemas.js +4 -2
- package/dist/shareLinks/types.d.ts +0 -1
- package/dist/shareLinks/types.js +0 -1
- package/dist/solveCache/interface.d.ts +2 -3
- package/dist/solveCache/interface.js +0 -1
- package/dist/storage/assetClasses.d.ts +4 -8
- package/dist/storage/assetClasses.js +6 -21
- package/dist/storage/cacheBust.d.ts +0 -1
- package/dist/storage/cacheBust.js +5 -3
- package/dist/storage/image.d.ts +8 -5
- package/dist/storage/image.js +74 -12
- package/dist/storage/index.d.ts +2 -4
- package/dist/storage/index.js +2 -3
- package/dist/storage/interface.d.ts +11 -3
- package/dist/storage/interface.js +0 -1
- package/dist/storage/safeKey.d.ts +7 -0
- package/dist/storage/safeKey.js +12 -0
- package/dist/testing/index.d.ts +5 -2
- package/dist/testing/index.js +3 -2
- package/dist/testing/suites/apiTokenStoreSuite.d.ts +0 -1
- package/dist/testing/suites/apiTokenStoreSuite.js +0 -1
- package/dist/testing/suites/auditQuerySuite.d.ts +18 -0
- package/dist/testing/suites/auditQuerySuite.js +73 -0
- package/dist/testing/suites/authProviderSuite.d.ts +14 -3
- package/dist/testing/suites/authProviderSuite.js +57 -32
- package/dist/testing/suites/computeServerStoreSuite.d.ts +1 -2
- package/dist/testing/suites/computeServerStoreSuite.js +68 -4
- package/dist/testing/suites/definitionStoreSuite.d.ts +2 -1
- package/dist/testing/suites/definitionStoreSuite.js +48 -16
- package/dist/testing/suites/emailLinkAuthSuite.d.ts +2 -5
- package/dist/testing/suites/emailLinkAuthSuite.js +1 -9
- package/dist/testing/suites/eventSinkSuite.d.ts +0 -1
- package/dist/testing/suites/eventSinkSuite.js +9 -1
- package/dist/testing/suites/helpers.d.ts +5 -1
- package/dist/testing/suites/helpers.js +7 -1
- package/dist/testing/suites/inviteStoreSuite.d.ts +0 -1
- package/dist/testing/suites/inviteStoreSuite.js +17 -7
- package/dist/testing/suites/oauthAuthSuite.d.ts +18 -0
- package/dist/testing/suites/oauthAuthSuite.js +26 -0
- package/dist/testing/suites/orgStoreSuite.d.ts +5 -1
- package/dist/testing/suites/orgStoreSuite.js +26 -7
- package/dist/testing/suites/platformPermissionStoreSuite.d.ts +0 -5
- package/dist/testing/suites/platformPermissionStoreSuite.js +12 -63
- package/dist/testing/suites/platformProjectGrantStoreSuite.d.ts +0 -1
- package/dist/testing/suites/platformProjectGrantStoreSuite.js +0 -5
- package/dist/testing/suites/projectStoreSuite.d.ts +5 -1
- package/dist/testing/suites/projectStoreSuite.js +6 -6
- package/dist/testing/suites/shareLinkStoreSuite.d.ts +2 -1
- package/dist/testing/suites/shareLinkStoreSuite.js +22 -25
- package/dist/testing/suites/solveMetricSinkSuite.d.ts +0 -1
- package/dist/testing/suites/solveMetricSinkSuite.js +2 -2
- package/dist/testing/suites/storageProviderSuite.d.ts +0 -1
- package/dist/testing/suites/storageProviderSuite.js +15 -10
- package/dist/testing/suites/userProfileStoreSuite.d.ts +1 -2
- package/dist/testing/suites/userProfileStoreSuite.js +42 -7
- package/dist/userProfile/index.d.ts +2 -2
- package/dist/userProfile/index.js +2 -2
- package/dist/userProfile/interface.d.ts +5 -6
- package/dist/userProfile/interface.js +0 -1
- package/dist/userProfile/types.d.ts +2 -1
- package/dist/userProfile/types.js +2 -1
- package/dist/utils/audit.d.ts +0 -1
- package/dist/utils/audit.js +0 -1
- package/dist/utils/index.d.ts +0 -2
- package/dist/utils/index.js +0 -1
- package/package.json +7 -6
- package/dist/access/index.d.ts.map +0 -1
- package/dist/access/index.js.map +0 -1
- package/dist/access/rules.d.ts.map +0 -1
- package/dist/access/rules.js.map +0 -1
- package/dist/apiTokens/index.d.ts.map +0 -1
- package/dist/apiTokens/index.js.map +0 -1
- package/dist/apiTokens/interface.d.ts.map +0 -1
- package/dist/apiTokens/interface.js.map +0 -1
- package/dist/apiTokens/scope.d.ts.map +0 -1
- package/dist/apiTokens/scope.js.map +0 -1
- package/dist/apiTokens/types.d.ts.map +0 -1
- package/dist/apiTokens/types.js.map +0 -1
- package/dist/auth/index.d.ts.map +0 -1
- package/dist/auth/index.js.map +0 -1
- package/dist/auth/interface.d.ts.map +0 -1
- package/dist/auth/interface.js.map +0 -1
- package/dist/auth/types.d.ts.map +0 -1
- package/dist/auth/types.js.map +0 -1
- package/dist/bindings/index.d.ts.map +0 -1
- package/dist/bindings/index.js.map +0 -1
- package/dist/bindings/interface.d.ts.map +0 -1
- package/dist/bindings/interface.js.map +0 -1
- package/dist/computeServer/index.d.ts.map +0 -1
- package/dist/computeServer/index.js.map +0 -1
- package/dist/computeServer/interface.d.ts.map +0 -1
- package/dist/computeServer/interface.js.map +0 -1
- package/dist/computeServer/secrets.d.ts.map +0 -1
- package/dist/computeServer/secrets.js.map +0 -1
- package/dist/computeServer/types.d.ts.map +0 -1
- package/dist/computeServer/types.js.map +0 -1
- package/dist/computeServer/utils.d.ts.map +0 -1
- package/dist/computeServer/utils.js.map +0 -1
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/context.d.ts.map +0 -1
- package/dist/context.js.map +0 -1
- package/dist/data/index.d.ts.map +0 -1
- package/dist/data/index.js.map +0 -1
- package/dist/data/interface.d.ts.map +0 -1
- package/dist/data/interface.js.map +0 -1
- package/dist/definitions/index.d.ts.map +0 -1
- package/dist/definitions/index.js.map +0 -1
- package/dist/definitions/interface.d.ts.map +0 -1
- package/dist/definitions/interface.js.map +0 -1
- package/dist/definitions/paths.d.ts.map +0 -1
- package/dist/definitions/paths.js.map +0 -1
- package/dist/definitions/schemas.d.ts.map +0 -1
- package/dist/definitions/schemas.js.map +0 -1
- package/dist/definitions/types.d.ts.map +0 -1
- package/dist/definitions/types.js.map +0 -1
- package/dist/errors/interface.d.ts.map +0 -1
- package/dist/errors/interface.js.map +0 -1
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js.map +0 -1
- package/dist/events/audit.d.ts.map +0 -1
- package/dist/events/audit.js.map +0 -1
- package/dist/events/index.d.ts.map +0 -1
- package/dist/events/index.js.map +0 -1
- package/dist/events/interface.d.ts.map +0 -1
- package/dist/events/interface.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/invites/index.d.ts.map +0 -1
- package/dist/invites/index.js.map +0 -1
- package/dist/invites/interface.d.ts.map +0 -1
- package/dist/invites/interface.js.map +0 -1
- package/dist/invites/types.d.ts.map +0 -1
- package/dist/invites/types.js.map +0 -1
- package/dist/logging/interface.d.ts.map +0 -1
- package/dist/logging/interface.js.map +0 -1
- package/dist/metrics/interface.d.ts.map +0 -1
- package/dist/metrics/interface.js.map +0 -1
- package/dist/notifications/index.d.ts.map +0 -1
- package/dist/notifications/index.js.map +0 -1
- package/dist/notifications/interface.d.ts.map +0 -1
- package/dist/notifications/interface.js.map +0 -1
- package/dist/notifications/types.d.ts.map +0 -1
- package/dist/notifications/types.js.map +0 -1
- package/dist/organizations/index.d.ts.map +0 -1
- package/dist/organizations/index.js.map +0 -1
- package/dist/organizations/interface.d.ts.map +0 -1
- package/dist/organizations/interface.js.map +0 -1
- package/dist/organizations/paths.d.ts.map +0 -1
- package/dist/organizations/paths.js.map +0 -1
- package/dist/organizations/schemas.d.ts.map +0 -1
- package/dist/organizations/schemas.js.map +0 -1
- package/dist/organizations/types.d.ts.map +0 -1
- package/dist/organizations/types.js.map +0 -1
- package/dist/pagination.d.ts.map +0 -1
- package/dist/pagination.js.map +0 -1
- package/dist/permissions/index.d.ts.map +0 -1
- package/dist/permissions/index.js.map +0 -1
- package/dist/permissions/interface.d.ts.map +0 -1
- package/dist/permissions/interface.js.map +0 -1
- package/dist/permissions/types.d.ts.map +0 -1
- package/dist/permissions/types.js.map +0 -1
- package/dist/platformProjects/index.d.ts.map +0 -1
- package/dist/platformProjects/index.js.map +0 -1
- package/dist/platformProjects/interface.d.ts.map +0 -1
- package/dist/platformProjects/interface.js.map +0 -1
- package/dist/platformProjects/schemas.d.ts.map +0 -1
- package/dist/platformProjects/schemas.js.map +0 -1
- package/dist/platformProjects/types.d.ts.map +0 -1
- package/dist/platformProjects/types.js.map +0 -1
- package/dist/projects/index.d.ts.map +0 -1
- package/dist/projects/index.js.map +0 -1
- package/dist/projects/interface.d.ts.map +0 -1
- package/dist/projects/interface.js.map +0 -1
- package/dist/projects/schemas.d.ts.map +0 -1
- package/dist/projects/schemas.js.map +0 -1
- package/dist/projects/types.d.ts.map +0 -1
- package/dist/projects/types.js.map +0 -1
- package/dist/shareLinks/index.d.ts.map +0 -1
- package/dist/shareLinks/index.js.map +0 -1
- package/dist/shareLinks/interface.d.ts.map +0 -1
- package/dist/shareLinks/interface.js.map +0 -1
- package/dist/shareLinks/schemas.d.ts.map +0 -1
- package/dist/shareLinks/schemas.js.map +0 -1
- package/dist/shareLinks/types.d.ts.map +0 -1
- package/dist/shareLinks/types.js.map +0 -1
- package/dist/solveCache/interface.d.ts.map +0 -1
- package/dist/solveCache/interface.js.map +0 -1
- package/dist/storage/assetClasses.d.ts.map +0 -1
- package/dist/storage/assetClasses.js.map +0 -1
- package/dist/storage/cacheBust.d.ts.map +0 -1
- package/dist/storage/cacheBust.js.map +0 -1
- package/dist/storage/image.d.ts.map +0 -1
- package/dist/storage/image.js.map +0 -1
- package/dist/storage/index.d.ts.map +0 -1
- package/dist/storage/index.js.map +0 -1
- package/dist/storage/interface.d.ts.map +0 -1
- package/dist/storage/interface.js.map +0 -1
- package/dist/testing/index.d.ts.map +0 -1
- package/dist/testing/index.js.map +0 -1
- package/dist/testing/suites/apiTokenStoreSuite.d.ts.map +0 -1
- package/dist/testing/suites/apiTokenStoreSuite.js.map +0 -1
- package/dist/testing/suites/authProviderSuite.d.ts.map +0 -1
- package/dist/testing/suites/authProviderSuite.js.map +0 -1
- package/dist/testing/suites/computeServerStoreSuite.d.ts.map +0 -1
- package/dist/testing/suites/computeServerStoreSuite.js.map +0 -1
- package/dist/testing/suites/definitionStoreSuite.d.ts.map +0 -1
- package/dist/testing/suites/definitionStoreSuite.js.map +0 -1
- package/dist/testing/suites/emailLinkAuthSuite.d.ts.map +0 -1
- package/dist/testing/suites/emailLinkAuthSuite.js.map +0 -1
- package/dist/testing/suites/eventSinkSuite.d.ts.map +0 -1
- package/dist/testing/suites/eventSinkSuite.js.map +0 -1
- package/dist/testing/suites/helpers.d.ts.map +0 -1
- package/dist/testing/suites/helpers.js.map +0 -1
- package/dist/testing/suites/inviteStoreSuite.d.ts.map +0 -1
- package/dist/testing/suites/inviteStoreSuite.js.map +0 -1
- package/dist/testing/suites/orgStoreSuite.d.ts.map +0 -1
- package/dist/testing/suites/orgStoreSuite.js.map +0 -1
- package/dist/testing/suites/platformPermissionStoreSuite.d.ts.map +0 -1
- package/dist/testing/suites/platformPermissionStoreSuite.js.map +0 -1
- package/dist/testing/suites/platformProjectGrantStoreSuite.d.ts.map +0 -1
- package/dist/testing/suites/platformProjectGrantStoreSuite.js.map +0 -1
- package/dist/testing/suites/projectStoreSuite.d.ts.map +0 -1
- package/dist/testing/suites/projectStoreSuite.js.map +0 -1
- package/dist/testing/suites/shareLinkStoreSuite.d.ts.map +0 -1
- package/dist/testing/suites/shareLinkStoreSuite.js.map +0 -1
- package/dist/testing/suites/solveMetricSinkSuite.d.ts.map +0 -1
- package/dist/testing/suites/solveMetricSinkSuite.js.map +0 -1
- package/dist/testing/suites/storageProviderSuite.d.ts.map +0 -1
- package/dist/testing/suites/storageProviderSuite.js.map +0 -1
- package/dist/testing/suites/userProfileStoreSuite.d.ts.map +0 -1
- package/dist/testing/suites/userProfileStoreSuite.js.map +0 -1
- package/dist/userProfile/index.d.ts.map +0 -1
- package/dist/userProfile/index.js.map +0 -1
- package/dist/userProfile/interface.d.ts.map +0 -1
- package/dist/userProfile/interface.js.map +0 -1
- package/dist/userProfile/types.d.ts.map +0 -1
- package/dist/userProfile/types.js.map +0 -1
- package/dist/utils/audit.d.ts.map +0 -1
- package/dist/utils/audit.js.map +0 -1
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js.map +0 -1
package/dist/testing/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
export { runAuthProviderConformance } from './suites/authProviderSuite.js';
|
|
1
|
+
export { runAuthCoreConformance, runAuthProviderConformance, runPasswordAuthConformance } from './suites/authProviderSuite.js';
|
|
2
|
+
export { runOAuthAuthConformance } from './suites/oauthAuthSuite.js';
|
|
3
|
+
export { runAuditQueryConformance } from './suites/auditQuerySuite.js';
|
|
2
4
|
export { runEmailLinkAuthConformance } from './suites/emailLinkAuthSuite.js';
|
|
3
5
|
export { runDefinitionStoreConformance } from './suites/definitionStoreSuite.js';
|
|
4
6
|
export { runOrgStoreConformance } from './suites/orgStoreSuite.js';
|
|
@@ -13,4 +15,3 @@ export { runSolveMetricSinkConformance } from './suites/solveMetricSinkSuite.js'
|
|
|
13
15
|
export { runPlatformPermissionStoreConformance } from './suites/platformPermissionStoreSuite.js';
|
|
14
16
|
export { runPlatformProjectGrantStoreConformance } from './suites/platformProjectGrantStoreSuite.js';
|
|
15
17
|
export { runApiTokenStoreConformance } from './suites/apiTokenStoreSuite.js';
|
|
16
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapter conformance suite for IAuditQuery, read through the sink that writes the
|
|
3
|
+
* rows. Also holds an IEventSink to what the query shows: per-actor order.
|
|
4
|
+
*/
|
|
5
|
+
import type { IAuditQuery } from '../../events/audit.js';
|
|
6
|
+
import type { IEventSink } from '../../events/interface.js';
|
|
7
|
+
export interface AuditQueryConformanceOptions {
|
|
8
|
+
name: string;
|
|
9
|
+
/** A query and the sink that feeds it, over storage that starts empty. */
|
|
10
|
+
createStores: () => Promise<{
|
|
11
|
+
query: IAuditQuery;
|
|
12
|
+
sink: IEventSink;
|
|
13
|
+
}> | {
|
|
14
|
+
query: IAuditQuery;
|
|
15
|
+
sink: IEventSink;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export declare function runAuditQueryConformance(opts: AuditQueryConformanceOptions): void;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapter conformance suite for IAuditQuery, read through the sink that writes the
|
|
3
|
+
* rows. Also holds an IEventSink to what the query shows: per-actor order.
|
|
4
|
+
*/
|
|
5
|
+
import { describe, it, expect } from 'vitest';
|
|
6
|
+
import { makeSystemCtx, makeUuid } from './helpers.js';
|
|
7
|
+
const ctx = makeSystemCtx();
|
|
8
|
+
const deleted = (orgId, actorId) => ({
|
|
9
|
+
type: 'org.deleted',
|
|
10
|
+
orgId,
|
|
11
|
+
actorId
|
|
12
|
+
});
|
|
13
|
+
const created = (orgId, actorId) => ({
|
|
14
|
+
type: 'org.created',
|
|
15
|
+
orgId,
|
|
16
|
+
actorId
|
|
17
|
+
});
|
|
18
|
+
export function runAuditQueryConformance(opts) {
|
|
19
|
+
const { name, createStores } = opts;
|
|
20
|
+
describe(`IAuditQuery conformance: ${name}`, () => {
|
|
21
|
+
it("returns one actor's events newest first, in the order they were emitted", async () => {
|
|
22
|
+
const { query, sink } = await createStores();
|
|
23
|
+
const actor = makeUuid();
|
|
24
|
+
const orgs = [makeUuid(), makeUuid(), makeUuid()];
|
|
25
|
+
for (const org of orgs)
|
|
26
|
+
await sink.emit(deleted(org, actor));
|
|
27
|
+
const { rows } = await query.list(ctx, { actorId: actor });
|
|
28
|
+
expect(rows.map((r) => r.data.orgId)).toEqual([...orgs].reverse());
|
|
29
|
+
});
|
|
30
|
+
it('filters by type and actor', async () => {
|
|
31
|
+
const { query, sink } = await createStores();
|
|
32
|
+
const actor = makeUuid();
|
|
33
|
+
await sink.emit(created(makeUuid(), actor));
|
|
34
|
+
await sink.emit(deleted(makeUuid(), actor));
|
|
35
|
+
await sink.emit(deleted(makeUuid(), makeUuid()));
|
|
36
|
+
const { rows } = await query.list(ctx, { actorId: actor, types: ['org.deleted'] });
|
|
37
|
+
expect(rows.map((r) => r.type)).toEqual(['org.deleted']);
|
|
38
|
+
});
|
|
39
|
+
it('honours the time bounds', async () => {
|
|
40
|
+
const { query, sink } = await createStores();
|
|
41
|
+
const actor = makeUuid();
|
|
42
|
+
await sink.emit(deleted(makeUuid(), actor));
|
|
43
|
+
const future = new Date(Date.now() + 60_000).toISOString();
|
|
44
|
+
const past = new Date(Date.now() - 60_000).toISOString();
|
|
45
|
+
expect((await query.list(ctx, { actorId: actor, sinceIso: future })).rows).toEqual([]);
|
|
46
|
+
expect((await query.list(ctx, { actorId: actor, untilIso: past })).rows).toEqual([]);
|
|
47
|
+
});
|
|
48
|
+
it('pages through every row exactly once', async () => {
|
|
49
|
+
const { query, sink } = await createStores();
|
|
50
|
+
const actor = makeUuid();
|
|
51
|
+
for (let i = 0; i < 5; i++)
|
|
52
|
+
await sink.emit(deleted(makeUuid(), actor));
|
|
53
|
+
const seen = [];
|
|
54
|
+
let cursor;
|
|
55
|
+
for (;;) {
|
|
56
|
+
const page = await query.list(ctx, { actorId: actor, limit: 2, cursor });
|
|
57
|
+
seen.push(...page.rows.map((r) => r.id));
|
|
58
|
+
if (!page.nextCursor)
|
|
59
|
+
break;
|
|
60
|
+
cursor = page.nextCursor;
|
|
61
|
+
}
|
|
62
|
+
expect(seen).toHaveLength(5);
|
|
63
|
+
expect(new Set(seen).size).toBe(5);
|
|
64
|
+
});
|
|
65
|
+
it('still returns a row for a fractional limit', async () => {
|
|
66
|
+
const { query, sink } = await createStores();
|
|
67
|
+
const actor = makeUuid();
|
|
68
|
+
await sink.emit(deleted(makeUuid(), actor));
|
|
69
|
+
const { rows } = await query.list(ctx, { actorId: actor, limit: 0.5 });
|
|
70
|
+
expect(rows).toHaveLength(1);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
}
|
|
@@ -8,8 +8,8 @@ export interface AuthProviderConformanceOptions {
|
|
|
8
8
|
* for password-capable providers. The factory is responsible for seeding
|
|
9
9
|
* the admin user (e.g. via `createUserWithPassword`) before returning.
|
|
10
10
|
*
|
|
11
|
-
* `adminEmail` defaults to `''
|
|
12
|
-
*
|
|
11
|
+
* `adminEmail` defaults to `''`; a password provider should return the seeded
|
|
12
|
+
* admin's email.
|
|
13
13
|
*/
|
|
14
14
|
createProvider: () => Promise<{
|
|
15
15
|
provider: IAuthProvider;
|
|
@@ -26,6 +26,17 @@ export interface AuthProviderConformanceOptions {
|
|
|
26
26
|
* When false those methods are expected to return null / 'not_supported'.
|
|
27
27
|
*/
|
|
28
28
|
userManagement?: boolean;
|
|
29
|
+
/** The provider has no `passwordAuth`, so only the core cases apply. */
|
|
30
|
+
passwordless?: boolean;
|
|
31
|
+
/** `passwordAuth.registerUser` is on, so its cases run. */
|
|
32
|
+
selfRegistration?: boolean;
|
|
29
33
|
}
|
|
34
|
+
/** Cases every auth provider must pass, password or not. */
|
|
35
|
+
export declare function runAuthCoreConformance(opts: Pick<AuthProviderConformanceOptions, 'name' | 'createProvider'>): void;
|
|
36
|
+
/** Cases for a provider with `passwordAuth`. */
|
|
37
|
+
export declare function runPasswordAuthConformance(opts: AuthProviderConformanceOptions): void;
|
|
38
|
+
/**
|
|
39
|
+
* Both of the above, gated on what the provider has. New cases go behind an option
|
|
40
|
+
* so a third-party adapter does not turn red on upgrade.
|
|
41
|
+
*/
|
|
30
42
|
export declare function runAuthProviderConformance(opts: AuthProviderConformanceOptions): void;
|
|
31
|
-
//# sourceMappingURL=authProviderSuite.d.ts.map
|
|
@@ -1,19 +1,10 @@
|
|
|
1
1
|
// Conformance suite for IAuthProvider: token round-trips, identity, password auth, admin management.
|
|
2
2
|
import { describe, it, expect } from 'vitest';
|
|
3
3
|
import { makeUuid } from './helpers.js';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
it('verifyLogin returns a session token that verifyToken accepts', async () => {
|
|
9
|
-
const { provider, adminPassword, adminEmail = '' } = await createProvider();
|
|
10
|
-
const result = await provider.passwordAuth.verifyLogin(adminEmail, adminPassword);
|
|
11
|
-
expect(result.kind).toBe('success');
|
|
12
|
-
if (result.kind !== 'success')
|
|
13
|
-
return;
|
|
14
|
-
const verified = await provider.verifyToken(result.sessionToken);
|
|
15
|
-
expect(verified?.id).toBe(result.user.id);
|
|
16
|
-
});
|
|
4
|
+
/** Cases every auth provider must pass, password or not. */
|
|
5
|
+
export function runAuthCoreConformance(opts) {
|
|
6
|
+
const { name, createProvider } = opts;
|
|
7
|
+
describe(`IAuthProvider core conformance: ${name}`, () => {
|
|
17
8
|
it('verifyToken returns null for a garbage token', async () => {
|
|
18
9
|
const { provider } = await createProvider();
|
|
19
10
|
const result = await provider.verifyToken('not-a-valid-token');
|
|
@@ -24,35 +15,57 @@ export function runAuthProviderConformance(opts) {
|
|
|
24
15
|
const result = await provider.verifyToken('');
|
|
25
16
|
expect(result).toBeNull();
|
|
26
17
|
});
|
|
18
|
+
it('getUser returns null for unknown id', async () => {
|
|
19
|
+
const { provider } = await createProvider();
|
|
20
|
+
// Valid UUID shape but not an actual user — stricter backends (Postgres
|
|
21
|
+
// uuid columns) reject non-UUID ids outright, so we never send those.
|
|
22
|
+
const result = await provider.getUser(makeUuid());
|
|
23
|
+
expect(result).toBeNull();
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/** Cases for a provider with `passwordAuth`. */
|
|
28
|
+
export function runPasswordAuthConformance(opts) {
|
|
29
|
+
const { name, createProvider, userManagement = false, selfRegistration = false } = opts;
|
|
30
|
+
describe(`IAuthProvider password conformance: ${name}`, () => {
|
|
31
|
+
// Token round-trips
|
|
32
|
+
it('verifyLogin returns a session token that verifyToken accepts', async () => {
|
|
33
|
+
const { provider, adminPassword, adminEmail = '' } = await createProvider();
|
|
34
|
+
const result = await provider.passwordAuth.verifyLogin(adminEmail, adminPassword);
|
|
35
|
+
expect(result.kind).toBe('success');
|
|
36
|
+
if (result.kind !== 'success')
|
|
37
|
+
return;
|
|
38
|
+
const verified = await provider.verifyToken(result.sessionToken);
|
|
39
|
+
expect(verified?.id).toBe(result.user.id);
|
|
40
|
+
});
|
|
27
41
|
// Password auth (only runs when passwordAuth is present)
|
|
28
42
|
it('verifyLogin returns success with correct password', async () => {
|
|
29
43
|
const { provider, adminPassword, adminEmail = '' } = await createProvider();
|
|
30
|
-
if (!provider.passwordAuth)
|
|
31
|
-
return;
|
|
32
44
|
const result = await provider.passwordAuth.verifyLogin(adminEmail, adminPassword);
|
|
33
45
|
expect(result.kind).toBe('success');
|
|
34
46
|
if (result.kind !== 'success')
|
|
35
47
|
return;
|
|
36
|
-
// Identity-only
|
|
48
|
+
// Identity-only: platform permissions live on IPlatformPermissionStore.
|
|
37
49
|
expect(result.user.id).toBeTruthy();
|
|
38
50
|
expect(typeof result.sessionToken).toBe('string');
|
|
39
51
|
expect(result.sessionToken.length).toBeGreaterThan(0);
|
|
40
52
|
});
|
|
53
|
+
if (selfRegistration) {
|
|
54
|
+
it('registerUser creates an account that can sign in', async () => {
|
|
55
|
+
const { provider } = await createProvider();
|
|
56
|
+
const email = `register-${makeUuid()}@example.com`;
|
|
57
|
+
const user = await provider.passwordAuth.registerUser(email, 'pass12345678');
|
|
58
|
+
expect(user?.email).toBe(email);
|
|
59
|
+
const login = await provider.passwordAuth.verifyLogin(email, 'pass12345678');
|
|
60
|
+
expect(login.kind).toBe('success');
|
|
61
|
+
});
|
|
62
|
+
}
|
|
41
63
|
it('verifyLogin returns failed for wrong password', async () => {
|
|
42
64
|
const { provider, adminEmail = '' } = await createProvider();
|
|
43
|
-
if (!provider.passwordAuth)
|
|
44
|
-
return;
|
|
45
65
|
const result = await provider.passwordAuth.verifyLogin(adminEmail, 'wrong-password-xyz');
|
|
46
66
|
expect(result.kind).toBe('failed');
|
|
47
67
|
});
|
|
48
68
|
// getUser
|
|
49
|
-
it('getUser returns null for unknown id', async () => {
|
|
50
|
-
const { provider } = await createProvider();
|
|
51
|
-
// Valid UUID shape but not an actual user — stricter backends (Postgres
|
|
52
|
-
// uuid columns) reject non-UUID ids outright, so we never send those.
|
|
53
|
-
const result = await provider.getUser(makeUuid());
|
|
54
|
-
expect(result).toBeNull();
|
|
55
|
-
});
|
|
56
69
|
// ============================================================================
|
|
57
70
|
// User management (opt-in)
|
|
58
71
|
// ============================================================================
|
|
@@ -102,12 +115,8 @@ export function runAuthProviderConformance(opts) {
|
|
|
102
115
|
const result = await provider.deleteUser(makeUuid());
|
|
103
116
|
expect(result).toBe('not_found');
|
|
104
117
|
});
|
|
105
|
-
//
|
|
106
|
-
//
|
|
107
|
-
// callers consult `countInstanceAdminsExcluding` before destructive
|
|
108
|
-
// ops. Auth-side delete/disable just deletes the identity and
|
|
109
|
-
// trusts the caller. See `runPlatformPermissionStoreConformance`
|
|
110
|
-
// for the invariant tests.
|
|
118
|
+
// Auth-side delete/disable trusts the caller: the sole-`instance_admin`
|
|
119
|
+
// invariant is `runPlatformPermissionStoreConformance`'s to test.
|
|
111
120
|
it('createUserWithPassword returns an identity record without profile fields', async () => {
|
|
112
121
|
const { provider } = await createProvider();
|
|
113
122
|
const user = await provider.passwordAuth.createUserWithPassword(`new-${makeUuid()}@example.com`, 'pass12345678');
|
|
@@ -127,6 +136,14 @@ export function runAuthProviderConformance(opts) {
|
|
|
127
136
|
const fetched = await provider.getUser(created.id);
|
|
128
137
|
expect(fetched?.disabled).toBe(true);
|
|
129
138
|
});
|
|
139
|
+
it('verifyLogin refuses a disabled user', async () => {
|
|
140
|
+
const { provider } = await createProvider();
|
|
141
|
+
const email = `disabled-${makeUuid()}@example.com`;
|
|
142
|
+
const created = await provider.passwordAuth.createUserWithPassword(email, 'pass12345678');
|
|
143
|
+
await provider.disableUser(created.id);
|
|
144
|
+
const result = await provider.passwordAuth.verifyLogin(email, 'pass12345678');
|
|
145
|
+
expect(result).toMatchObject({ kind: 'failed' });
|
|
146
|
+
});
|
|
130
147
|
it('disableUser returns not_found for unknown user', async () => {
|
|
131
148
|
const { provider } = await createProvider();
|
|
132
149
|
const result = await provider.disableUser(makeUuid());
|
|
@@ -156,4 +173,12 @@ export function runAuthProviderConformance(opts) {
|
|
|
156
173
|
}
|
|
157
174
|
});
|
|
158
175
|
}
|
|
159
|
-
|
|
176
|
+
/**
|
|
177
|
+
* Both of the above, gated on what the provider has. New cases go behind an option
|
|
178
|
+
* so a third-party adapter does not turn red on upgrade.
|
|
179
|
+
*/
|
|
180
|
+
export function runAuthProviderConformance(opts) {
|
|
181
|
+
runAuthCoreConformance(opts);
|
|
182
|
+
if (!opts.passwordless)
|
|
183
|
+
runPasswordAuthConformance(opts);
|
|
184
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Adapter conformance suite for IComputeServerStore.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Servers are scoped (platform vs. org-private), with a global
|
|
5
5
|
* `defaultServerId` and per-org `orgDefaults`. The store surface exposes
|
|
6
6
|
* scope-targeted mutations; visibility filtering is done by callers via
|
|
7
7
|
* the pure helpers in `@selvajs/platform`.
|
|
@@ -18,4 +18,3 @@ export interface ComputeServerStoreConformanceOptions {
|
|
|
18
18
|
seedOrg?: (orgId: string) => Promise<void>;
|
|
19
19
|
}
|
|
20
20
|
export declare function runComputeServerStoreConformance(opts: ComputeServerStoreConformanceOptions): void;
|
|
21
|
-
//# sourceMappingURL=computeServerStoreSuite.d.ts.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Adapter conformance suite for IComputeServerStore.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Servers are scoped (platform vs. org-private), with a global
|
|
5
5
|
* `defaultServerId` and per-org `orgDefaults`. The store surface exposes
|
|
6
6
|
* scope-targeted mutations; visibility filtering is done by callers via
|
|
7
7
|
* the pure helpers in `@selvajs/platform`.
|
|
@@ -65,11 +65,76 @@ export function runComputeServerStoreConformance(opts) {
|
|
|
65
65
|
it('getConfig on empty returns an empty servers list', async () => {
|
|
66
66
|
const store = await createStore();
|
|
67
67
|
const got = await store.getConfig(SYSTEM_CONTEXT);
|
|
68
|
-
expect(
|
|
68
|
+
expect(got.servers).toEqual([]);
|
|
69
|
+
});
|
|
70
|
+
it('getConfig hides keys unless asked, and reports that one is stored', async () => {
|
|
71
|
+
const store = await createStore();
|
|
72
|
+
const id = makeUuid();
|
|
73
|
+
await store.savePlatformServers(SYSTEM_CONTEXT, [
|
|
74
|
+
{
|
|
75
|
+
id,
|
|
76
|
+
scope: 'platform',
|
|
77
|
+
sharedWith: 'all',
|
|
78
|
+
label: 'Keyed',
|
|
79
|
+
serverUrl: 'http://compute.test',
|
|
80
|
+
apiKey: 'rhino-key'
|
|
81
|
+
}
|
|
82
|
+
], id);
|
|
83
|
+
const plain = await store.getConfig(SYSTEM_CONTEXT);
|
|
84
|
+
expect(plain.servers[0].apiKey).toBeUndefined();
|
|
85
|
+
expect(plain.servers[0].hasApiKey).toBe(true);
|
|
86
|
+
const keyed = await store.getConfig(SYSTEM_CONTEXT, { includeApiKeys: true });
|
|
87
|
+
expect(keyed.servers[0].apiKey).toBe('rhino-key');
|
|
88
|
+
});
|
|
89
|
+
it('getServerApiKey returns one key, and undefined for an unknown server', async () => {
|
|
90
|
+
const store = await createStore();
|
|
91
|
+
const id = makeUuid();
|
|
92
|
+
await store.savePlatformServers(SYSTEM_CONTEXT, [
|
|
93
|
+
{
|
|
94
|
+
id,
|
|
95
|
+
scope: 'platform',
|
|
96
|
+
sharedWith: 'all',
|
|
97
|
+
label: 'Keyed',
|
|
98
|
+
serverUrl: 'http://compute.test',
|
|
99
|
+
apiKey: 'rhino-key'
|
|
100
|
+
}
|
|
101
|
+
], id);
|
|
102
|
+
expect(await store.getServerApiKey(SYSTEM_CONTEXT, id)).toBe('rhino-key');
|
|
103
|
+
expect(await store.getServerApiKey(SYSTEM_CONTEXT, makeUuid())).toBeUndefined();
|
|
104
|
+
});
|
|
105
|
+
it('verifySecrets passes on keys this store wrote', async () => {
|
|
106
|
+
const store = await createStore();
|
|
107
|
+
const id = makeUuid();
|
|
108
|
+
await store.savePlatformServers(SYSTEM_CONTEXT, [
|
|
109
|
+
{
|
|
110
|
+
id,
|
|
111
|
+
scope: 'platform',
|
|
112
|
+
sharedWith: 'all',
|
|
113
|
+
label: 'Keyed',
|
|
114
|
+
serverUrl: 'http://compute.test',
|
|
115
|
+
apiKey: 'rhino-key'
|
|
116
|
+
}
|
|
117
|
+
], id);
|
|
118
|
+
const report = await store.verifySecrets?.();
|
|
119
|
+
if (report)
|
|
120
|
+
expect(report).toEqual({ ok: true, failures: [], plaintextFound: false });
|
|
69
121
|
});
|
|
70
122
|
// ============================================================================
|
|
71
|
-
// Org-private servers + orgDefaults
|
|
123
|
+
// Org-private servers + orgDefaults
|
|
72
124
|
// ============================================================================
|
|
125
|
+
it('saveOrgServers ignores an entry that is not an org server', async () => {
|
|
126
|
+
const store = await createStore();
|
|
127
|
+
const orgId = await seed();
|
|
128
|
+
const stray = {
|
|
129
|
+
id: makeUuid(),
|
|
130
|
+
scope: 'platform',
|
|
131
|
+
sharedWith: 'all',
|
|
132
|
+
label: 'Stray',
|
|
133
|
+
serverUrl: 'http://compute.test'
|
|
134
|
+
};
|
|
135
|
+
await store.saveOrgServers(SYSTEM_CONTEXT, orgId, [stray]);
|
|
136
|
+
expect((await store.getConfig(SYSTEM_CONTEXT)).servers).toEqual([]);
|
|
137
|
+
});
|
|
73
138
|
it('saveOrgServers stores rows owned by the org', async () => {
|
|
74
139
|
const store = await createStore();
|
|
75
140
|
const orgId = await seed();
|
|
@@ -136,4 +201,3 @@ export function runComputeServerStoreConformance(opts) {
|
|
|
136
201
|
});
|
|
137
202
|
});
|
|
138
203
|
}
|
|
139
|
-
//# sourceMappingURL=computeServerStoreSuite.js.map
|
|
@@ -26,6 +26,8 @@ export interface DefinitionTestScope {
|
|
|
26
26
|
* Must reference a real row for FK-enforcing adapters.
|
|
27
27
|
*/
|
|
28
28
|
secondaryProjectId: string;
|
|
29
|
+
/** Used by the ctx-isolation cases when `projectId` is one anyone can see. */
|
|
30
|
+
privateProjectId?: string;
|
|
29
31
|
/** Optional third user id for ctx-isolation tests. Required when ctxIsolation is set. */
|
|
30
32
|
secondaryUserId?: string;
|
|
31
33
|
/** Token for `secondaryUserId`, when used. */
|
|
@@ -49,4 +51,3 @@ export interface DefinitionStoreConformanceOptions {
|
|
|
49
51
|
ctxIsolation?: boolean;
|
|
50
52
|
}
|
|
51
53
|
export declare function runDefinitionStoreConformance(opts: DefinitionStoreConformanceOptions): void;
|
|
52
|
-
//# sourceMappingURL=definitionStoreSuite.d.ts.map
|
|
@@ -6,25 +6,21 @@
|
|
|
6
6
|
* reference protection (Permissions spec §6), and error shapes.
|
|
7
7
|
*/
|
|
8
8
|
import { describe, it, expect } from 'vitest';
|
|
9
|
-
import {
|
|
9
|
+
import { makeSeedHelpers, makeUuid } from './helpers.js';
|
|
10
10
|
const DEFAULT_SCOPE = {
|
|
11
11
|
ownerId: 'user-1',
|
|
12
12
|
projectId: 'project-1',
|
|
13
13
|
secondaryProjectId: 'project-2',
|
|
14
14
|
secondaryUserId: 'user-b'
|
|
15
15
|
};
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
|
|
19
|
-
const tokens = new Map();
|
|
20
|
-
function ctx(userId, opts = {}) {
|
|
21
|
-
return makeCtx(userId, { ...opts, sessionToken: tokens.get(userId) });
|
|
22
|
-
}
|
|
16
|
+
// `scopeFor` registers the scope's tokens, so `ctx` runs as the right user on an
|
|
17
|
+
// adapter with DB-side auth (Supabase RLS). This suite seeds nobody itself.
|
|
18
|
+
const { ctx, registerToken } = makeSeedHelpers(async (userId) => ({ userId }));
|
|
23
19
|
function recordTokensFromScope(scope) {
|
|
24
20
|
if (scope.ownerSessionToken)
|
|
25
|
-
|
|
21
|
+
registerToken(scope.ownerId, scope.ownerSessionToken);
|
|
26
22
|
if (scope.secondaryUserId && scope.secondaryUserSessionToken) {
|
|
27
|
-
|
|
23
|
+
registerToken(scope.secondaryUserId, scope.secondaryUserSessionToken);
|
|
28
24
|
}
|
|
29
25
|
}
|
|
30
26
|
function record(scope, overrides = {}) {
|
|
@@ -163,6 +159,15 @@ export function runDefinitionStoreConformance(opts) {
|
|
|
163
159
|
expect(got?.displayName).toBe('New');
|
|
164
160
|
expect(got.updatedAt >= created.updatedAt).toBe(true);
|
|
165
161
|
});
|
|
162
|
+
it('update with null tags clears them', async () => {
|
|
163
|
+
const store = await createStore();
|
|
164
|
+
const scope = await scopeFor();
|
|
165
|
+
const guid = makeUuid();
|
|
166
|
+
await store.create(ctx(scope.ownerId), record(scope, { guid, tags: ['roof'] }));
|
|
167
|
+
await store.update(ctx(scope.ownerId), guid, { tags: null });
|
|
168
|
+
const got = await store.get(ctx(scope.ownerId), guid);
|
|
169
|
+
expect(got?.tags ?? []).toEqual([]);
|
|
170
|
+
});
|
|
166
171
|
it('solveCacheLimit round-trips: absent → inherit, set → value, null → cleared', async () => {
|
|
167
172
|
const store = await createStore();
|
|
168
173
|
const scope = await scopeFor();
|
|
@@ -180,6 +185,35 @@ export function runDefinitionStoreConformance(opts) {
|
|
|
180
185
|
await store.update(ctx(scope.ownerId), guid, { solveCacheLimit: null });
|
|
181
186
|
expect((await store.get(ctx(scope.ownerId), guid))?.solveCacheLimit).toBeUndefined();
|
|
182
187
|
});
|
|
188
|
+
it('sourceDocumentId round-trips through create, update and clear', async () => {
|
|
189
|
+
const store = await createStore();
|
|
190
|
+
const scope = await scopeFor();
|
|
191
|
+
const guid = makeUuid();
|
|
192
|
+
const docA = makeUuid();
|
|
193
|
+
const docB = makeUuid();
|
|
194
|
+
await store.create(ctx(scope.ownerId), record(scope, { guid, sourceDocumentId: docA }));
|
|
195
|
+
expect((await store.get(ctx(scope.ownerId), guid))?.sourceDocumentId).toBe(docA);
|
|
196
|
+
await store.update(ctx(scope.ownerId), guid, { sourceDocumentId: docB });
|
|
197
|
+
expect((await store.get(ctx(scope.ownerId), guid))?.sourceDocumentId).toBe(docB);
|
|
198
|
+
await store.update(ctx(scope.ownerId), guid, { sourceDocumentId: null });
|
|
199
|
+
expect((await store.get(ctx(scope.ownerId), guid))?.sourceDocumentId).toBeUndefined();
|
|
200
|
+
});
|
|
201
|
+
it('list filters by sourceDocumentId in the query', async () => {
|
|
202
|
+
const store = await createStore();
|
|
203
|
+
const scope = await scopeFor();
|
|
204
|
+
const doc = makeUuid();
|
|
205
|
+
const match = makeUuid();
|
|
206
|
+
await store.create(ctx(scope.ownerId), record(scope, { guid: match, sourceDocumentId: doc }));
|
|
207
|
+
await store.create(ctx(scope.ownerId), record(scope, { guid: makeUuid(), sourceDocumentId: makeUuid() }));
|
|
208
|
+
await store.create(ctx(scope.ownerId), record(scope, { guid: makeUuid() }));
|
|
209
|
+
const page = await store.list(ctx(scope.ownerId), {
|
|
210
|
+
sourceDocumentId: doc,
|
|
211
|
+
projectIds: [scope.projectId],
|
|
212
|
+
limit: 1
|
|
213
|
+
});
|
|
214
|
+
expect(page.items.map((r) => r.guid)).toEqual([match]);
|
|
215
|
+
expect(page.nextCursor).toBeUndefined();
|
|
216
|
+
});
|
|
183
217
|
it('update on missing guid throws ProviderError with status 404', async () => {
|
|
184
218
|
const store = await createStore();
|
|
185
219
|
const scope = await scopeFor();
|
|
@@ -240,9 +274,8 @@ export function runDefinitionStoreConformance(opts) {
|
|
|
240
274
|
expect(got?.nextVersionNumber).toBe(4);
|
|
241
275
|
});
|
|
242
276
|
it('reserveNextVersionNumber mints a FRESH number after delete-latest (fileKeys never collide)', async () => {
|
|
243
|
-
// The
|
|
244
|
-
//
|
|
245
|
-
// counter must hand out a number BEYOND any deleted version's.
|
|
277
|
+
// The counter exists because max(existing)+1 would reuse a deleted number
|
|
278
|
+
// and collide the fileKey, so it must go beyond any deleted version's.
|
|
246
279
|
const store = await createStore();
|
|
247
280
|
const scope = await scopeFor();
|
|
248
281
|
const guid = makeUuid();
|
|
@@ -545,7 +578,7 @@ export function runDefinitionStoreConformance(opts) {
|
|
|
545
578
|
if (!otherUser)
|
|
546
579
|
throw new Error('ctxIsolation requires scope.secondaryUserId');
|
|
547
580
|
const guid = makeUuid();
|
|
548
|
-
await store.create(ctx(scope.ownerId), record(scope, { guid }));
|
|
581
|
+
await store.create(ctx(scope.ownerId), record(scope, { guid, projectId: scope.privateProjectId ?? scope.projectId }));
|
|
549
582
|
const page = await store.list(ctx(otherUser));
|
|
550
583
|
expect(page.items.map((r) => r.guid)).not.toContain(guid);
|
|
551
584
|
});
|
|
@@ -556,11 +589,10 @@ export function runDefinitionStoreConformance(opts) {
|
|
|
556
589
|
if (!otherUser)
|
|
557
590
|
throw new Error('ctxIsolation requires scope.secondaryUserId');
|
|
558
591
|
const guid = makeUuid();
|
|
559
|
-
await store.create(ctx(scope.ownerId), record(scope, { guid }));
|
|
592
|
+
await store.create(ctx(scope.ownerId), record(scope, { guid, projectId: scope.privateProjectId ?? scope.projectId }));
|
|
560
593
|
const got = await store.get(ctx(otherUser), guid);
|
|
561
594
|
expect(got).toBeNull();
|
|
562
595
|
});
|
|
563
596
|
}
|
|
564
597
|
});
|
|
565
598
|
}
|
|
566
|
-
//# sourceMappingURL=definitionStoreSuite.js.map
|
|
@@ -18,15 +18,12 @@ export interface EmailLinkAuthConformanceOptions {
|
|
|
18
18
|
* with self-signup enabled or disabled — the suite's tests are robust to
|
|
19
19
|
* either, since they don't assume new users get created.
|
|
20
20
|
*
|
|
21
|
-
* `
|
|
22
|
-
*
|
|
23
|
-
* one the adapter must reject as malformed.
|
|
21
|
+
* `invalidEmail` is an address the adapter must reject as malformed. A valid
|
|
22
|
+
* send isn't tested here: it needs real mail delivery.
|
|
24
23
|
*/
|
|
25
24
|
createAdapter: () => Promise<{
|
|
26
25
|
adapter: IEmailLinkAuth;
|
|
27
|
-
validEmail: string;
|
|
28
26
|
invalidEmail: string;
|
|
29
27
|
}>;
|
|
30
28
|
}
|
|
31
29
|
export declare function runEmailLinkAuthConformance(opts: EmailLinkAuthConformanceOptions): void;
|
|
32
|
-
//# sourceMappingURL=emailLinkAuthSuite.d.ts.map
|
|
@@ -36,16 +36,8 @@ export function runEmailLinkAuthConformance(opts) {
|
|
|
36
36
|
const result = await adapter.sendMagicLink(invalidEmail, 'https://example.com/auth/email/callback');
|
|
37
37
|
expect(result.ok).toBe(false);
|
|
38
38
|
if (!result.ok) {
|
|
39
|
-
expect(
|
|
39
|
+
expect(result.reason).toBe('invalid_email');
|
|
40
40
|
}
|
|
41
41
|
});
|
|
42
|
-
// `sendMagicLink` for a valid email is intentionally NOT tested here:
|
|
43
|
-
// it requires real Supabase project credentials with email delivery
|
|
44
|
-
// enabled, and we'd be asserting on side-effects (mail sent) we can't
|
|
45
|
-
// observe. Adapter-specific integration tests cover that path.
|
|
46
|
-
void '';
|
|
47
42
|
});
|
|
48
|
-
// keep `createAdapter` referenced for adapters that have nothing more to test
|
|
49
|
-
void createAdapter;
|
|
50
43
|
}
|
|
51
|
-
//# sourceMappingURL=emailLinkAuthSuite.js.map
|
|
@@ -151,6 +151,15 @@ export function runEventSinkConformance(opts) {
|
|
|
151
151
|
await expect(provider.orgs.createOrg(ctx, makeOrg({ id: orgId, ownerId: actorId }))).rejects.toThrow();
|
|
152
152
|
expect(sink.ofType('org.created')).toHaveLength(0);
|
|
153
153
|
});
|
|
154
|
+
it('stamps tokenId on an event from an API-token request', async () => {
|
|
155
|
+
const tokenId = makeUuid();
|
|
156
|
+
const keyed = {
|
|
157
|
+
...ctx,
|
|
158
|
+
apiScope: { tokenId, scopes: [], expiresAt: '2099-01-01T00:00:00.000Z' }
|
|
159
|
+
};
|
|
160
|
+
await provider.orgs.createOrg(keyed, makeOrg({ id: makeUuid(), ownerId: actorId }));
|
|
161
|
+
expect(sink.ofType('org.created')[0]).toMatchObject({ actorId, tokenId });
|
|
162
|
+
});
|
|
154
163
|
it('system-context mutations emit with actorId="system"', async () => {
|
|
155
164
|
const sysCtx = {
|
|
156
165
|
userId: '',
|
|
@@ -261,4 +270,3 @@ function makeShareLink(overrides) {
|
|
|
261
270
|
solveCount: 0
|
|
262
271
|
};
|
|
263
272
|
}
|
|
264
|
-
//# sourceMappingURL=eventSinkSuite.js.map
|
|
@@ -14,6 +14,11 @@ export declare function makeCtx(userId: string, opts?: {
|
|
|
14
14
|
orgPermissions?: RequestContext['orgPermissions'];
|
|
15
15
|
sessionToken?: string;
|
|
16
16
|
}): RequestContext;
|
|
17
|
+
/**
|
|
18
|
+
* A system context holding no permissions of its own, for proving a store leans on
|
|
19
|
+
* `system` rather than on a permission `SYSTEM_CONTEXT` happens to carry.
|
|
20
|
+
*/
|
|
21
|
+
export declare function makeSystemCtx(userId?: string): RequestContext;
|
|
17
22
|
export declare function makeUuid(): string;
|
|
18
23
|
/**
|
|
19
24
|
* Optional hook adapters pass when their backend enforces referential
|
|
@@ -52,4 +57,3 @@ export declare function makeSeedHelpers(seedUser: SeedUserFn): {
|
|
|
52
57
|
registerToken: (userId: string, sessionToken: string) => void;
|
|
53
58
|
tokens: Map<string, string>;
|
|
54
59
|
};
|
|
55
|
-
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -17,6 +17,13 @@ export function makeCtx(userId, opts = {}) {
|
|
|
17
17
|
adapterContext: opts.sessionToken ? { sessionToken: opts.sessionToken } : undefined
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* A system context holding no permissions of its own, for proving a store leans on
|
|
22
|
+
* `system` rather than on a permission `SYSTEM_CONTEXT` happens to carry.
|
|
23
|
+
*/
|
|
24
|
+
export function makeSystemCtx(userId = '') {
|
|
25
|
+
return { userId, platformPermissions: [], orgPermissions: [], system: true };
|
|
26
|
+
}
|
|
20
27
|
export function makeUuid() {
|
|
21
28
|
return crypto.randomUUID();
|
|
22
29
|
}
|
|
@@ -44,4 +51,3 @@ export function makeSeedHelpers(seedUser) {
|
|
|
44
51
|
}
|
|
45
52
|
return { seed, ctx, registerToken, tokens };
|
|
46
53
|
}
|
|
47
|
-
//# sourceMappingURL=helpers.js.map
|