@selvajs/supabase-provider 0.14.4-beta.0 → 0.15.0-beta.2
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/LICENSE +1 -1
- package/README.md +2 -0
- package/dist/auth/SupabaseAuthProvider.d.ts.map +1 -1
- package/dist/auth/SupabaseAuthProvider.js +7 -14
- package/dist/auth/SupabaseAuthProvider.js.map +1 -1
- package/dist/data/SupabaseComputeServerStore.d.ts +14 -3
- package/dist/data/SupabaseComputeServerStore.d.ts.map +1 -1
- package/dist/data/SupabaseComputeServerStore.js +67 -16
- package/dist/data/SupabaseComputeServerStore.js.map +1 -1
- package/dist/data/SupabaseDataProvider.d.ts +36 -8
- package/dist/data/SupabaseDataProvider.d.ts.map +1 -1
- package/dist/data/SupabaseDataProvider.js +119 -15
- package/dist/data/SupabaseDataProvider.js.map +1 -1
- package/dist/data/SupabaseDefinitionStore.d.ts +1 -0
- package/dist/data/SupabaseDefinitionStore.d.ts.map +1 -1
- package/dist/data/SupabaseDefinitionStore.js +41 -4
- package/dist/data/SupabaseDefinitionStore.js.map +1 -1
- package/dist/data/SupabaseEventSink.d.ts +5 -2
- package/dist/data/SupabaseEventSink.d.ts.map +1 -1
- package/dist/data/SupabaseEventSink.js +20 -3
- package/dist/data/SupabaseEventSink.js.map +1 -1
- package/dist/data/SupabaseSolveMetricSink.d.ts +49 -4
- package/dist/data/SupabaseSolveMetricSink.d.ts.map +1 -1
- package/dist/data/SupabaseSolveMetricSink.js +109 -19
- package/dist/data/SupabaseSolveMetricSink.js.map +1 -1
- package/dist/data/index.d.ts +1 -0
- package/dist/data/index.d.ts.map +1 -1
- package/dist/data/index.js +1 -0
- package/dist/data/index.js.map +1 -1
- package/dist/data/migrationHead.d.ts +14 -0
- package/dist/data/migrationHead.d.ts.map +1 -0
- package/dist/data/migrationHead.js +14 -0
- package/dist/data/migrationHead.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/permissions/SupabasePlatformPermissionStore.d.ts +5 -3
- package/dist/permissions/SupabasePlatformPermissionStore.d.ts.map +1 -1
- package/dist/permissions/SupabasePlatformPermissionStore.js +17 -30
- package/dist/permissions/SupabasePlatformPermissionStore.js.map +1 -1
- package/dist/storage/SupabaseStorageProvider.d.ts.map +1 -1
- package/dist/storage/SupabaseStorageProvider.js +3 -0
- package/dist/storage/SupabaseStorageProvider.js.map +1 -1
- package/package.json +23 -14
- package/supabase/migrations/20260712120000_user_profiles_disabled_and_gin.sql +95 -0
- package/supabase/migrations/20260712123000_selva_migration_head_fn.sql +38 -0
- package/supabase/migrations/20260713120000_selva_next_version_number.sql +59 -0
- package/supabase/migrations/20260713140000_selva_solve_cache_limit.sql +15 -0
- package/supabase/migrations/20260716120000_definition_status_and_audit_version.sql +36 -0
- package/supabase/migrations/20260716130000_erase_user_audit_email.sql +36 -0
- package/supabase/migrations/20260717120000_compute_server_has_api_key.sql +20 -0
- package/dist/auth/__tests__/conformance.test.d.ts +0 -2
- package/dist/auth/__tests__/conformance.test.d.ts.map +0 -1
- package/dist/auth/__tests__/conformance.test.js +0 -76
- package/dist/auth/__tests__/conformance.test.js.map +0 -1
- package/dist/auth/__tests__/token-verification.test.d.ts +0 -13
- package/dist/auth/__tests__/token-verification.test.d.ts.map +0 -1
- package/dist/auth/__tests__/token-verification.test.js +0 -135
- package/dist/auth/__tests__/token-verification.test.js.map +0 -1
- package/dist/data/__tests__/compute-server-conformance.test.d.ts +0 -2
- package/dist/data/__tests__/compute-server-conformance.test.d.ts.map +0 -1
- package/dist/data/__tests__/compute-server-conformance.test.js +0 -45
- package/dist/data/__tests__/compute-server-conformance.test.js.map +0 -1
- package/dist/data/__tests__/compute-server-encryption.test.d.ts +0 -12
- package/dist/data/__tests__/compute-server-encryption.test.d.ts.map +0 -1
- package/dist/data/__tests__/compute-server-encryption.test.js +0 -143
- package/dist/data/__tests__/compute-server-encryption.test.js.map +0 -1
- package/dist/data/__tests__/definition-conformance.test.d.ts +0 -2
- package/dist/data/__tests__/definition-conformance.test.d.ts.map +0 -1
- package/dist/data/__tests__/definition-conformance.test.js +0 -85
- package/dist/data/__tests__/definition-conformance.test.js.map +0 -1
- package/dist/data/__tests__/event-sink-conformance.test.d.ts +0 -2
- package/dist/data/__tests__/event-sink-conformance.test.d.ts.map +0 -1
- package/dist/data/__tests__/event-sink-conformance.test.js +0 -27
- package/dist/data/__tests__/event-sink-conformance.test.js.map +0 -1
- package/dist/data/__tests__/invite-conformance.test.d.ts +0 -2
- package/dist/data/__tests__/invite-conformance.test.d.ts.map +0 -1
- package/dist/data/__tests__/invite-conformance.test.js +0 -45
- package/dist/data/__tests__/invite-conformance.test.js.map +0 -1
- package/dist/data/__tests__/org-conformance.test.d.ts +0 -2
- package/dist/data/__tests__/org-conformance.test.d.ts.map +0 -1
- package/dist/data/__tests__/org-conformance.test.js +0 -29
- package/dist/data/__tests__/org-conformance.test.js.map +0 -1
- package/dist/data/__tests__/project-conformance.test.d.ts +0 -2
- package/dist/data/__tests__/project-conformance.test.d.ts.map +0 -1
- package/dist/data/__tests__/project-conformance.test.js +0 -57
- package/dist/data/__tests__/project-conformance.test.js.map +0 -1
- package/dist/data/__tests__/share-link-concurrency.test.d.ts +0 -22
- package/dist/data/__tests__/share-link-concurrency.test.d.ts.map +0 -1
- package/dist/data/__tests__/share-link-concurrency.test.js +0 -115
- package/dist/data/__tests__/share-link-concurrency.test.js.map +0 -1
- package/dist/data/__tests__/share-link-conformance.test.d.ts +0 -2
- package/dist/data/__tests__/share-link-conformance.test.d.ts.map +0 -1
- package/dist/data/__tests__/share-link-conformance.test.js +0 -88
- package/dist/data/__tests__/share-link-conformance.test.js.map +0 -1
- package/dist/data/__tests__/solve-metric-sink-conformance.test.d.ts +0 -2
- package/dist/data/__tests__/solve-metric-sink-conformance.test.d.ts.map +0 -1
- package/dist/data/__tests__/solve-metric-sink-conformance.test.js +0 -52
- package/dist/data/__tests__/solve-metric-sink-conformance.test.js.map +0 -1
- package/dist/data/__tests__/test-helpers.d.ts +0 -52
- package/dist/data/__tests__/test-helpers.d.ts.map +0 -1
- package/dist/data/__tests__/test-helpers.js +0 -177
- package/dist/data/__tests__/test-helpers.js.map +0 -1
- package/dist/permissions/__tests__/conformance.test.d.ts +0 -2
- package/dist/permissions/__tests__/conformance.test.d.ts.map +0 -1
- package/dist/permissions/__tests__/conformance.test.js +0 -27
- package/dist/permissions/__tests__/conformance.test.js.map +0 -1
- package/dist/storage/__tests__/conformance.test.d.ts +0 -2
- package/dist/storage/__tests__/conformance.test.d.ts.map +0 -1
- package/dist/storage/__tests__/conformance.test.js +0 -149
- package/dist/storage/__tests__/conformance.test.js.map +0 -1
- package/dist/userProfile/__tests__/conformance.test.d.ts +0 -2
- package/dist/userProfile/__tests__/conformance.test.d.ts.map +0 -1
- package/dist/userProfile/__tests__/conformance.test.js +0 -38
- package/dist/userProfile/__tests__/conformance.test.js.map +0 -1
- package/src/auth/SupabaseAuthProvider.ts +0 -600
- package/src/auth/__tests__/conformance.test.ts +0 -78
- package/src/auth/__tests__/token-verification.test.ts +0 -158
- package/src/auth/index.ts +0 -2
- package/src/cli/sync-migrations.ts +0 -133
- package/src/data/SupabaseAuditQuery.ts +0 -103
- package/src/data/SupabaseComputeServerStore.ts +0 -382
- package/src/data/SupabaseDataProvider.ts +0 -153
- package/src/data/SupabaseDefinitionStore.ts +0 -527
- package/src/data/SupabaseEventSink.ts +0 -30
- package/src/data/SupabaseInviteStore.ts +0 -171
- package/src/data/SupabaseOrgStore.ts +0 -508
- package/src/data/SupabaseProjectStore.ts +0 -431
- package/src/data/SupabaseShareLinkStore.ts +0 -176
- package/src/data/SupabaseSolveMetricSink.ts +0 -38
- package/src/data/__tests__/compute-server-conformance.test.ts +0 -46
- package/src/data/__tests__/compute-server-encryption.test.ts +0 -173
- package/src/data/__tests__/definition-conformance.test.ts +0 -89
- package/src/data/__tests__/event-sink-conformance.test.ts +0 -32
- package/src/data/__tests__/invite-conformance.test.ts +0 -46
- package/src/data/__tests__/org-conformance.test.ts +0 -30
- package/src/data/__tests__/project-conformance.test.ts +0 -57
- package/src/data/__tests__/share-link-concurrency.test.ts +0 -124
- package/src/data/__tests__/share-link-conformance.test.ts +0 -87
- package/src/data/__tests__/solve-metric-sink-conformance.test.ts +0 -59
- package/src/data/__tests__/test-helpers.ts +0 -188
- package/src/data/client.ts +0 -173
- package/src/data/errors.ts +0 -45
- package/src/data/index.ts +0 -29
- package/src/data/pagination.ts +0 -68
- package/src/data/query.ts +0 -22
- package/src/data/rowStamp.ts +0 -48
- package/src/index.ts +0 -42
- package/src/permissions/SupabasePlatformPermissionStore.ts +0 -161
- package/src/permissions/__tests__/conformance.test.ts +0 -28
- package/src/permissions/index.ts +0 -1
- package/src/storage/SupabaseStorageProvider.ts +0 -182
- package/src/storage/__tests__/conformance.test.ts +0 -152
- package/src/storage/index.ts +0 -2
- package/src/userProfile/SupabaseUserProfileProvider.ts +0 -177
- package/src/userProfile/__tests__/conformance.test.ts +0 -39
- package/src/userProfile/index.ts +0 -1
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CI-runnable (no live stack) unit tests for at-rest encryption of
|
|
3
|
-
* `compute_servers.api_key`. Uses a minimal fake of the Supabase query builder
|
|
4
|
-
* that records `insert` payloads and serves canned `select` rows, so we can
|
|
5
|
-
* assert the exact bytes that would reach the DB without a real Postgres.
|
|
6
|
-
*
|
|
7
|
-
* The security property under test: a plaintext apiKey handed to the store is
|
|
8
|
-
* NEVER written verbatim — the DB only ever sees an `enc:v1:` envelope — and it
|
|
9
|
-
* round-trips back to plaintext on read.
|
|
10
|
-
*/
|
|
11
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
12
|
-
import { randomBytes } from 'node:crypto';
|
|
13
|
-
import { isEncryptedSecret, decryptSecret } from '@selvajs/platform/computeServer';
|
|
14
|
-
import { SupabaseComputeServerStore } from '../SupabaseComputeServerStore.js';
|
|
15
|
-
const SYSTEM_CTX = { userId: '', system: true };
|
|
16
|
-
const KEY = randomBytes(32);
|
|
17
|
-
/**
|
|
18
|
-
* Records every `insert` payload and returns canned rows for each table's
|
|
19
|
-
* `select`. Only the fragments the store actually chains are implemented; the
|
|
20
|
-
* builder is thenable so `await client.from(...).select(...)` resolves.
|
|
21
|
-
*/
|
|
22
|
-
function fakeBundle(selectRows = {}) {
|
|
23
|
-
const inserted = {};
|
|
24
|
-
function builder(table) {
|
|
25
|
-
const result = { data: selectRows[table] ?? [], error: null };
|
|
26
|
-
const chain = {
|
|
27
|
-
select: () => ({
|
|
28
|
-
...chain,
|
|
29
|
-
eq: () => ({ ...chain, maybeSingle: async () => ({ data: null, error: null }) }),
|
|
30
|
-
then: (resolve) => resolve(result)
|
|
31
|
-
}),
|
|
32
|
-
insert: (rows) => {
|
|
33
|
-
inserted[table] = (inserted[table] ?? []).concat(rows);
|
|
34
|
-
return { error: null };
|
|
35
|
-
},
|
|
36
|
-
delete: () => ({ eq: () => ({ eq: () => ({ error: null }), error: null }) }),
|
|
37
|
-
update: () => ({ eq: () => ({ error: null }) }),
|
|
38
|
-
upsert: () => ({ error: null })
|
|
39
|
-
};
|
|
40
|
-
return chain;
|
|
41
|
-
}
|
|
42
|
-
const client = { from: (t) => builder(t) };
|
|
43
|
-
const bundle = {
|
|
44
|
-
serviceClient: client,
|
|
45
|
-
forRequest: () => client
|
|
46
|
-
};
|
|
47
|
-
return { bundle, inserted };
|
|
48
|
-
}
|
|
49
|
-
describe('SupabaseComputeServerStore — apiKey encryption at rest', () => {
|
|
50
|
-
beforeEach(() => vi.restoreAllMocks());
|
|
51
|
-
it('encrypts apiKey before insert — DB never sees plaintext', async () => {
|
|
52
|
-
const { bundle, inserted } = fakeBundle();
|
|
53
|
-
const store = new SupabaseComputeServerStore(bundle, KEY);
|
|
54
|
-
await store.savePlatformServers(SYSTEM_CTX, [
|
|
55
|
-
{
|
|
56
|
-
id: 's1',
|
|
57
|
-
label: 'prod',
|
|
58
|
-
serverUrl: 'https://compute.example.com',
|
|
59
|
-
apiKey: 'super-secret-key',
|
|
60
|
-
scope: 'platform',
|
|
61
|
-
sharedWith: 'all'
|
|
62
|
-
}
|
|
63
|
-
], 's1');
|
|
64
|
-
const rows = inserted['compute_servers'];
|
|
65
|
-
expect(rows).toHaveLength(1);
|
|
66
|
-
expect(rows[0].api_key).not.toBe('super-secret-key');
|
|
67
|
-
expect(isEncryptedSecret(rows[0].api_key)).toBe(true);
|
|
68
|
-
// And it's genuinely our plaintext under the envelope.
|
|
69
|
-
expect(decryptSecret(rows[0].api_key, KEY)).toBe('super-secret-key');
|
|
70
|
-
});
|
|
71
|
-
it('decrypts apiKey on read — callers see plaintext', async () => {
|
|
72
|
-
// Seed the "DB" with an already-encrypted row.
|
|
73
|
-
const { encryptSecret } = await import('@selvajs/platform/computeServer');
|
|
74
|
-
const envelope = encryptSecret('round-trip-key', KEY);
|
|
75
|
-
const { bundle } = fakeBundle({
|
|
76
|
-
compute_servers: [
|
|
77
|
-
{
|
|
78
|
-
id: 's1',
|
|
79
|
-
scope: 'platform',
|
|
80
|
-
owner_org_id: null,
|
|
81
|
-
shared_with_all: true,
|
|
82
|
-
label: 'prod',
|
|
83
|
-
server_url: 'https://compute.example.com',
|
|
84
|
-
api_key: envelope,
|
|
85
|
-
timeout_ms: null,
|
|
86
|
-
retry_count: null
|
|
87
|
-
}
|
|
88
|
-
]
|
|
89
|
-
});
|
|
90
|
-
const store = new SupabaseComputeServerStore(bundle, KEY);
|
|
91
|
-
const config = await store.getConfig(SYSTEM_CTX);
|
|
92
|
-
expect(config.servers).toHaveLength(1);
|
|
93
|
-
expect(config.servers[0].apiKey).toBe('round-trip-key');
|
|
94
|
-
});
|
|
95
|
-
it('throws rather than persist plaintext when no key is configured', async () => {
|
|
96
|
-
const { bundle } = fakeBundle();
|
|
97
|
-
const store = new SupabaseComputeServerStore(bundle); // no key
|
|
98
|
-
await expect(store.savePlatformServers(SYSTEM_CTX, [
|
|
99
|
-
{
|
|
100
|
-
id: 's1',
|
|
101
|
-
label: 'prod',
|
|
102
|
-
serverUrl: 'https://compute.example.com',
|
|
103
|
-
apiKey: 'secret',
|
|
104
|
-
scope: 'platform',
|
|
105
|
-
sharedWith: 'all'
|
|
106
|
-
}
|
|
107
|
-
], 's1')).rejects.toThrow(/SELVA_AT_REST_KEY/);
|
|
108
|
-
});
|
|
109
|
-
it('verifySecrets flags a plaintext row', async () => {
|
|
110
|
-
const { bundle } = fakeBundle({
|
|
111
|
-
compute_servers: [{ id: 's1', label: 'legacy', api_key: 'raw-plaintext' }]
|
|
112
|
-
});
|
|
113
|
-
const store = new SupabaseComputeServerStore(bundle, KEY);
|
|
114
|
-
const report = await store.verifySecrets();
|
|
115
|
-
expect(report.ok).toBe(false);
|
|
116
|
-
expect(report.plaintextFound).toBe(true);
|
|
117
|
-
expect(report.failures).toEqual([
|
|
118
|
-
{ serverId: 's1', serverLabel: 'legacy', reason: 'plaintext_on_disk' }
|
|
119
|
-
]);
|
|
120
|
-
});
|
|
121
|
-
it('verifySecrets reports key_mismatch when the at-rest key rotated', async () => {
|
|
122
|
-
const { encryptSecret } = await import('@selvajs/platform/computeServer');
|
|
123
|
-
const envelope = encryptSecret('secret', randomBytes(32)); // different key
|
|
124
|
-
const { bundle } = fakeBundle({
|
|
125
|
-
compute_servers: [{ id: 's1', label: 'prod', api_key: envelope }]
|
|
126
|
-
});
|
|
127
|
-
const store = new SupabaseComputeServerStore(bundle, KEY);
|
|
128
|
-
const report = await store.verifySecrets();
|
|
129
|
-
expect(report.ok).toBe(false);
|
|
130
|
-
expect(report.plaintextFound).toBe(false);
|
|
131
|
-
expect(report.failures[0]).toMatchObject({ serverId: 's1', reason: 'key_mismatch' });
|
|
132
|
-
});
|
|
133
|
-
it('verifySecrets returns ok when every apiKey decrypts', async () => {
|
|
134
|
-
const { encryptSecret } = await import('@selvajs/platform/computeServer');
|
|
135
|
-
const { bundle } = fakeBundle({
|
|
136
|
-
compute_servers: [{ id: 's1', label: 'prod', api_key: encryptSecret('k', KEY) }]
|
|
137
|
-
});
|
|
138
|
-
const store = new SupabaseComputeServerStore(bundle, KEY);
|
|
139
|
-
const report = await store.verifySecrets();
|
|
140
|
-
expect(report).toEqual({ ok: true, failures: [], plaintextFound: false });
|
|
141
|
-
});
|
|
142
|
-
});
|
|
143
|
-
//# sourceMappingURL=compute-server-encryption.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"compute-server-encryption.test.js","sourceRoot":"","sources":["../../../src/data/__tests__/compute-server-encryption.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"definition-conformance.test.d.ts","sourceRoot":"","sources":["../../../src/data/__tests__/definition-conformance.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { describe, beforeEach, it } from 'vitest';
|
|
2
|
-
import { runDefinitionStoreConformance } from '@selvajs/platform/testing';
|
|
3
|
-
import { DEFAULT_ORG_PERMISSIONS } from '@selvajs/platform';
|
|
4
|
-
import { SupabaseDefinitionStore } from '../SupabaseDefinitionStore.js';
|
|
5
|
-
import { readEnv, resetAllData, seedUser } from './test-helpers.js';
|
|
6
|
-
const envCtx = readEnv();
|
|
7
|
-
if (!envCtx) {
|
|
8
|
-
describe.skip('SupabaseDefinitionStore (skipped: no live stack)', () => {
|
|
9
|
-
it('populate packages/providers/supabase/.env.test with Supabase creds to run these tests', () => { });
|
|
10
|
-
});
|
|
11
|
-
}
|
|
12
|
-
else {
|
|
13
|
-
describe('SupabaseDefinitionStore', () => {
|
|
14
|
-
beforeEach(async () => {
|
|
15
|
-
await resetAllData(envCtx);
|
|
16
|
-
});
|
|
17
|
-
runDefinitionStoreConformance({
|
|
18
|
-
name: 'SupabaseDefinitionStore',
|
|
19
|
-
createStore: () => new SupabaseDefinitionStore(envCtx.bundle),
|
|
20
|
-
createScope: async () => {
|
|
21
|
-
// Seed: 1 owner + 1 secondary user + 1 org + 2 projects. Definitions
|
|
22
|
-
// created in the suite FK to one of those two projects.
|
|
23
|
-
const { userId: ownerId, sessionToken: ownerSessionToken } = await seedUser(envCtx, '');
|
|
24
|
-
const { userId: secondaryUserId, sessionToken: secondaryUserSessionToken } = await seedUser(envCtx, '');
|
|
25
|
-
const orgId = crypto.randomUUID();
|
|
26
|
-
const projectId = crypto.randomUUID();
|
|
27
|
-
const secondaryProjectId = crypto.randomUUID();
|
|
28
|
-
const now = new Date().toISOString();
|
|
29
|
-
const admin = envCtx.adminClient;
|
|
30
|
-
const { error: orgError } = await admin.from('orgs').insert({
|
|
31
|
-
id: orgId,
|
|
32
|
-
name: 'Definition Test Org',
|
|
33
|
-
slug: `def-test-${orgId.slice(0, 8)}`,
|
|
34
|
-
owner_id: ownerId,
|
|
35
|
-
created_at: now,
|
|
36
|
-
updated_at: now
|
|
37
|
-
});
|
|
38
|
-
if (orgError)
|
|
39
|
-
throw orgError;
|
|
40
|
-
const { error: memberError } = await admin.from('org_members').insert({
|
|
41
|
-
org_id: orgId,
|
|
42
|
-
user_id: ownerId,
|
|
43
|
-
role: 'owner',
|
|
44
|
-
permissions: [...DEFAULT_ORG_PERMISSIONS.owner],
|
|
45
|
-
joined_at: now
|
|
46
|
-
});
|
|
47
|
-
if (memberError)
|
|
48
|
-
throw memberError;
|
|
49
|
-
const { error: p1Error } = await admin.from('projects').insert([
|
|
50
|
-
{
|
|
51
|
-
id: projectId,
|
|
52
|
-
org_id: orgId,
|
|
53
|
-
name: 'Project A',
|
|
54
|
-
slug: `proj-a-${projectId.slice(0, 8)}`,
|
|
55
|
-
visibility: 'public',
|
|
56
|
-
owner_id: ownerId,
|
|
57
|
-
created_at: now,
|
|
58
|
-
updated_at: now
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
id: secondaryProjectId,
|
|
62
|
-
org_id: orgId,
|
|
63
|
-
name: 'Project B',
|
|
64
|
-
slug: `proj-b-${secondaryProjectId.slice(0, 8)}`,
|
|
65
|
-
visibility: 'public',
|
|
66
|
-
owner_id: ownerId,
|
|
67
|
-
created_at: now,
|
|
68
|
-
updated_at: now
|
|
69
|
-
}
|
|
70
|
-
]);
|
|
71
|
-
if (p1Error)
|
|
72
|
-
throw p1Error;
|
|
73
|
-
return {
|
|
74
|
-
ownerId,
|
|
75
|
-
ownerSessionToken,
|
|
76
|
-
projectId,
|
|
77
|
-
secondaryProjectId,
|
|
78
|
-
secondaryUserId,
|
|
79
|
-
secondaryUserSessionToken
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
//# sourceMappingURL=definition-conformance.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"definition-conformance.test.js","sourceRoot":"","sources":["../../../src/data/__tests__/definition-conformance.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"event-sink-conformance.test.d.ts","sourceRoot":"","sources":["../../../src/data/__tests__/event-sink-conformance.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { describe, beforeEach, it } from 'vitest';
|
|
2
|
-
import { runEventSinkConformance } from '@selvajs/platform/testing';
|
|
3
|
-
import { SupabaseDataProvider } from '../SupabaseDataProvider.js';
|
|
4
|
-
import { readEnv, resetAllData, seedUser } from './test-helpers.js';
|
|
5
|
-
const envCtx = readEnv();
|
|
6
|
-
if (!envCtx) {
|
|
7
|
-
describe.skip('SupabaseDataProvider event-sink (skipped: no live stack)', () => {
|
|
8
|
-
it('populate packages/providers/supabase/.env.test with Supabase creds to run these tests', () => { });
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
else {
|
|
12
|
-
describe('SupabaseDataProvider event-sink', () => {
|
|
13
|
-
beforeEach(async () => {
|
|
14
|
-
await resetAllData(envCtx);
|
|
15
|
-
});
|
|
16
|
-
runEventSinkConformance({
|
|
17
|
-
name: 'SupabaseDataProvider',
|
|
18
|
-
createProvider: (sink) => SupabaseDataProvider.create({
|
|
19
|
-
supabaseUrl: envCtx.url,
|
|
20
|
-
anonKey: envCtx.anonKey,
|
|
21
|
-
serviceRoleKey: envCtx.serviceRoleKey
|
|
22
|
-
}, sink),
|
|
23
|
-
createActorId: () => seedUser(envCtx, '')
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
//# sourceMappingURL=event-sink-conformance.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"event-sink-conformance.test.js","sourceRoot":"","sources":["../../../src/data/__tests__/event-sink-conformance.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,uBAAuB,EAA2B,MAAM,2BAA2B,CAAC;AAC7F,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAEpE,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC;AAEzB,IAAI,CAAC,MAAM,EAAE,CAAC;IACb,QAAQ,CAAC,IAAI,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAC9E,EAAE,CAAC,uFAAuF,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACvG,CAAC,CAAC,CAAC;AACJ,CAAC;KAAM,CAAC;IACP,QAAQ,CAAC,iCAAiC,EAAE,GAAG,EAAE;QAChD,UAAU,CAAC,KAAK,IAAI,EAAE;YACrB,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;QAEH,uBAAuB,CAAC;YACvB,IAAI,EAAE,sBAAsB;YAC5B,cAAc,EAAE,CAAC,IAAwB,EAAE,EAAE,CAC5C,oBAAoB,CAAC,MAAM,CAC1B;gBACC,WAAW,EAAE,MAAM,CAAC,GAAG;gBACvB,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,cAAc,EAAE,MAAM,CAAC,cAAc;aACrC,EACD,IAAI,CACJ;YACF,aAAa,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;SACzC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"invite-conformance.test.d.ts","sourceRoot":"","sources":["../../../src/data/__tests__/invite-conformance.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { describe, beforeEach, it } from 'vitest';
|
|
2
|
-
import { runInviteStoreConformance } from '@selvajs/platform/testing';
|
|
3
|
-
import { DEFAULT_ORG_PERMISSIONS } from '@selvajs/platform';
|
|
4
|
-
import { SupabaseInviteStore } from '../SupabaseInviteStore.js';
|
|
5
|
-
import { readEnv, resetAllData, seedUser } from './test-helpers.js';
|
|
6
|
-
const envCtx = readEnv();
|
|
7
|
-
if (!envCtx) {
|
|
8
|
-
describe.skip('SupabaseInviteStore (skipped: no live stack)', () => {
|
|
9
|
-
it('populate packages/providers/supabase/.env.test with Supabase creds to run these tests', () => { });
|
|
10
|
-
});
|
|
11
|
-
}
|
|
12
|
-
else {
|
|
13
|
-
describe('SupabaseInviteStore', () => {
|
|
14
|
-
beforeEach(async () => {
|
|
15
|
-
await resetAllData(envCtx);
|
|
16
|
-
});
|
|
17
|
-
runInviteStoreConformance({
|
|
18
|
-
name: 'SupabaseInviteStore',
|
|
19
|
-
createStore: () => new SupabaseInviteStore(envCtx.bundle),
|
|
20
|
-
createScope: async () => {
|
|
21
|
-
const { userId: adminId, sessionToken: adminSessionToken } = await seedUser(envCtx, '');
|
|
22
|
-
const orgId = crypto.randomUUID();
|
|
23
|
-
const now = new Date().toISOString();
|
|
24
|
-
await envCtx.adminClient.from('orgs').insert({
|
|
25
|
-
id: orgId,
|
|
26
|
-
name: 'Invite Test Org',
|
|
27
|
-
slug: `invite-test-${orgId.slice(0, 8)}`,
|
|
28
|
-
owner_id: adminId,
|
|
29
|
-
created_at: now,
|
|
30
|
-
updated_at: now
|
|
31
|
-
});
|
|
32
|
-
await envCtx.adminClient.from('org_members').insert({
|
|
33
|
-
org_id: orgId,
|
|
34
|
-
user_id: adminId,
|
|
35
|
-
role: 'owner',
|
|
36
|
-
permissions: [...DEFAULT_ORG_PERMISSIONS.owner],
|
|
37
|
-
joined_at: now
|
|
38
|
-
});
|
|
39
|
-
return { adminId, adminSessionToken, orgId };
|
|
40
|
-
},
|
|
41
|
-
seedUser: (id) => seedUser(envCtx, id)
|
|
42
|
-
});
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
//# sourceMappingURL=invite-conformance.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"invite-conformance.test.js","sourceRoot":"","sources":["../../../src/data/__tests__/invite-conformance.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAEpE,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC;AAEzB,IAAI,CAAC,MAAM,EAAE,CAAC;IACb,QAAQ,CAAC,IAAI,CAAC,8CAA8C,EAAE,GAAG,EAAE;QAClE,EAAE,CAAC,uFAAuF,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACvG,CAAC,CAAC,CAAC;AACJ,CAAC;KAAM,CAAC;IACP,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;QACpC,UAAU,CAAC,KAAK,IAAI,EAAE;YACrB,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;QAEH,yBAAyB,CAAC;YACzB,IAAI,EAAE,qBAAqB;YAC3B,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC;YACzD,WAAW,EAAE,KAAK,IAAI,EAAE;gBACvB,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;gBACxF,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;gBAClC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;gBACrC,MAAM,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC;oBAC5C,EAAE,EAAE,KAAK;oBACT,IAAI,EAAE,iBAAiB;oBACvB,IAAI,EAAE,eAAe,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE;oBACxC,QAAQ,EAAE,OAAO;oBACjB,UAAU,EAAE,GAAG;oBACf,UAAU,EAAE,GAAG;iBACf,CAAC,CAAC;gBACH,MAAM,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC;oBACnD,MAAM,EAAE,KAAK;oBACb,OAAO,EAAE,OAAO;oBAChB,IAAI,EAAE,OAAO;oBACb,WAAW,EAAE,CAAC,GAAG,uBAAuB,CAAC,KAAK,CAAC;oBAC/C,SAAS,EAAE,GAAG;iBACd,CAAC,CAAC;gBACH,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,CAAC;YAC9C,CAAC;YACD,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;SACtC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"org-conformance.test.d.ts","sourceRoot":"","sources":["../../../src/data/__tests__/org-conformance.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { describe, beforeEach, it } from 'vitest';
|
|
2
|
-
import { runOrgStoreConformance } from '@selvajs/platform/testing';
|
|
3
|
-
import { SupabaseOrgStore } from '../SupabaseOrgStore.js';
|
|
4
|
-
import { SupabaseInviteStore } from '../SupabaseInviteStore.js';
|
|
5
|
-
import { SupabaseComputeServerStore } from '../SupabaseComputeServerStore.js';
|
|
6
|
-
import { readEnv, resetAllData, seedUser } from './test-helpers.js';
|
|
7
|
-
const envCtx = readEnv();
|
|
8
|
-
if (!envCtx) {
|
|
9
|
-
describe.skip('SupabaseOrgStore (skipped: no live stack)', () => {
|
|
10
|
-
it('populate packages/providers/supabase/.env.test with Supabase creds to run these tests', () => { });
|
|
11
|
-
});
|
|
12
|
-
}
|
|
13
|
-
else {
|
|
14
|
-
describe('SupabaseOrgStore', () => {
|
|
15
|
-
beforeEach(async () => {
|
|
16
|
-
await resetAllData(envCtx);
|
|
17
|
-
});
|
|
18
|
-
runOrgStoreConformance({
|
|
19
|
-
name: 'SupabaseOrgStore',
|
|
20
|
-
createStore: () => new SupabaseOrgStore(envCtx.bundle),
|
|
21
|
-
seedUser: (id) => seedUser(envCtx, id),
|
|
22
|
-
createCompanionStores: () => ({
|
|
23
|
-
invites: new SupabaseInviteStore(envCtx.bundle),
|
|
24
|
-
computeServer: new SupabaseComputeServerStore(envCtx.bundle)
|
|
25
|
-
})
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
//# sourceMappingURL=org-conformance.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"org-conformance.test.js","sourceRoot":"","sources":["../../../src/data/__tests__/org-conformance.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,0BAA0B,EAAE,MAAM,kCAAkC,CAAC;AAC9E,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAEpE,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC;AAEzB,IAAI,CAAC,MAAM,EAAE,CAAC;IACb,QAAQ,CAAC,IAAI,CAAC,2CAA2C,EAAE,GAAG,EAAE;QAC/D,EAAE,CAAC,uFAAuF,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACvG,CAAC,CAAC,CAAC;AACJ,CAAC;KAAM,CAAC;IACP,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;QACjC,UAAU,CAAC,KAAK,IAAI,EAAE;YACrB,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;QAEH,sBAAsB,CAAC;YACtB,IAAI,EAAE,kBAAkB;YACxB,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC;YACtD,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YACtC,qBAAqB,EAAE,GAAG,EAAE,CAAC,CAAC;gBAC7B,OAAO,EAAE,IAAI,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC;gBAC/C,aAAa,EAAE,IAAI,0BAA0B,CAAC,MAAM,CAAC,MAAM,CAAC;aAC5D,CAAC;SACF,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"project-conformance.test.d.ts","sourceRoot":"","sources":["../../../src/data/__tests__/project-conformance.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { describe, beforeEach, it } from 'vitest';
|
|
2
|
-
import { runProjectStoreConformance } from '@selvajs/platform/testing';
|
|
3
|
-
import { DEFAULT_ORG_PERMISSIONS } from '@selvajs/platform';
|
|
4
|
-
import { SupabaseProjectStore } from '../SupabaseProjectStore.js';
|
|
5
|
-
import { readEnv, resetAllData, seedUser } from './test-helpers.js';
|
|
6
|
-
const envCtx = readEnv();
|
|
7
|
-
if (!envCtx) {
|
|
8
|
-
describe.skip('SupabaseProjectStore (skipped: no live stack)', () => {
|
|
9
|
-
it('populate packages/providers/supabase/.env.test with Supabase creds to run these tests', () => { });
|
|
10
|
-
});
|
|
11
|
-
}
|
|
12
|
-
else {
|
|
13
|
-
describe('SupabaseProjectStore', () => {
|
|
14
|
-
beforeEach(async () => {
|
|
15
|
-
await resetAllData(envCtx);
|
|
16
|
-
});
|
|
17
|
-
runProjectStoreConformance({
|
|
18
|
-
name: 'SupabaseProjectStore',
|
|
19
|
-
createStore: async () => {
|
|
20
|
-
// Seed an owner + an org so the project tests have an anchor.
|
|
21
|
-
const { userId: ownerId, sessionToken: ownerSessionToken } = await seedUser(envCtx, '');
|
|
22
|
-
const orgId = crypto.randomUUID();
|
|
23
|
-
const now = new Date().toISOString();
|
|
24
|
-
const admin = envCtx.adminClient;
|
|
25
|
-
const { error: orgError } = await admin.from('orgs').insert({
|
|
26
|
-
id: orgId,
|
|
27
|
-
name: 'Conformance Org',
|
|
28
|
-
slug: `conformance-${orgId.slice(0, 8)}`,
|
|
29
|
-
owner_id: ownerId,
|
|
30
|
-
created_at: now,
|
|
31
|
-
updated_at: now
|
|
32
|
-
});
|
|
33
|
-
if (orgError)
|
|
34
|
-
throw orgError;
|
|
35
|
-
// And an owner membership with `manage_projects` so project
|
|
36
|
-
// creates pass the `has_org_permission` policy under RLS.
|
|
37
|
-
const { error: memberError } = await admin.from('org_members').insert({
|
|
38
|
-
org_id: orgId,
|
|
39
|
-
user_id: ownerId,
|
|
40
|
-
role: 'owner',
|
|
41
|
-
permissions: [...DEFAULT_ORG_PERMISSIONS.owner],
|
|
42
|
-
joined_at: now
|
|
43
|
-
});
|
|
44
|
-
if (memberError)
|
|
45
|
-
throw memberError;
|
|
46
|
-
return {
|
|
47
|
-
store: new SupabaseProjectStore(envCtx.bundle),
|
|
48
|
-
orgId,
|
|
49
|
-
ownerId,
|
|
50
|
-
ownerSessionToken
|
|
51
|
-
};
|
|
52
|
-
},
|
|
53
|
-
seedUser: (id) => seedUser(envCtx, id)
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
//# sourceMappingURL=project-conformance.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"project-conformance.test.js","sourceRoot":"","sources":["../../../src/data/__tests__/project-conformance.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAEpE,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC;AAEzB,IAAI,CAAC,MAAM,EAAE,CAAC;IACb,QAAQ,CAAC,IAAI,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACnE,EAAE,CAAC,uFAAuF,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACvG,CAAC,CAAC,CAAC;AACJ,CAAC;KAAM,CAAC;IACP,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;QACrC,UAAU,CAAC,KAAK,IAAI,EAAE;YACrB,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;QAEH,0BAA0B,CAAC;YAC1B,IAAI,EAAE,sBAAsB;YAC5B,WAAW,EAAE,KAAK,IAAI,EAAE;gBACvB,8DAA8D;gBAC9D,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;gBACxF,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;gBAClC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;gBACrC,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC;gBACjC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC;oBAC3D,EAAE,EAAE,KAAK;oBACT,IAAI,EAAE,iBAAiB;oBACvB,IAAI,EAAE,eAAe,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE;oBACxC,QAAQ,EAAE,OAAO;oBACjB,UAAU,EAAE,GAAG;oBACf,UAAU,EAAE,GAAG;iBACf,CAAC,CAAC;gBACH,IAAI,QAAQ;oBAAE,MAAM,QAAQ,CAAC;gBAC7B,4DAA4D;gBAC5D,0DAA0D;gBAC1D,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC;oBACrE,MAAM,EAAE,KAAK;oBACb,OAAO,EAAE,OAAO;oBAChB,IAAI,EAAE,OAAO;oBACb,WAAW,EAAE,CAAC,GAAG,uBAAuB,CAAC,KAAK,CAAC;oBAC/C,SAAS,EAAE,GAAG;iBACd,CAAC,CAAC;gBACH,IAAI,WAAW;oBAAE,MAAM,WAAW,CAAC;gBAEnC,OAAO;oBACN,KAAK,EAAE,IAAI,oBAAoB,CAAC,MAAM,CAAC,MAAM,CAAC;oBAC9C,KAAK;oBACL,OAAO;oBACP,iBAAiB;iBACjB,CAAC;YACH,CAAC;YACD,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;SACtC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Audit Q4/Q5 — the concurrent-solve guarantee for share-link caps.
|
|
3
|
-
*
|
|
4
|
-
* `tryIncrementSolveCount` is the load-bearing race-sensitive method: the
|
|
5
|
-
* `/api/compute` endpoint calls it BEFORE solving and turns a `null` return
|
|
6
|
-
* (cap hit) into HTTP 429. Under concurrent solves against one capped link, the
|
|
7
|
-
* cap must hold exactly — no overshoot, no lost update handing two solves the
|
|
8
|
-
* same slot. Supabase provides this via the SECURITY DEFINER
|
|
9
|
-
* `try_increment_share_link_solve_count` RPC, which does the check-and-increment
|
|
10
|
-
* in a single statement.
|
|
11
|
-
*
|
|
12
|
-
* This lives in the Supabase suite (not the shared conformance suite or the app
|
|
13
|
-
* route tests) because it is the ONLY backend that actually provides the
|
|
14
|
-
* guarantee: the local provider's whole-file read-modify-write is a documented
|
|
15
|
-
* dev-scale tradeoff and is not concurrency-safe. Skipped without a live stack,
|
|
16
|
-
* matching the other conformance tests here.
|
|
17
|
-
*
|
|
18
|
-
* Complements the sequential cap/count tests at
|
|
19
|
-
* `packages/selva/src/routes/api/compute/__tests__/solve-cap-and-count.test.ts`.
|
|
20
|
-
*/
|
|
21
|
-
export {};
|
|
22
|
-
//# sourceMappingURL=share-link-concurrency.test.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"share-link-concurrency.test.d.ts","sourceRoot":"","sources":["../../../src/data/__tests__/share-link-concurrency.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG"}
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Audit Q4/Q5 — the concurrent-solve guarantee for share-link caps.
|
|
3
|
-
*
|
|
4
|
-
* `tryIncrementSolveCount` is the load-bearing race-sensitive method: the
|
|
5
|
-
* `/api/compute` endpoint calls it BEFORE solving and turns a `null` return
|
|
6
|
-
* (cap hit) into HTTP 429. Under concurrent solves against one capped link, the
|
|
7
|
-
* cap must hold exactly — no overshoot, no lost update handing two solves the
|
|
8
|
-
* same slot. Supabase provides this via the SECURITY DEFINER
|
|
9
|
-
* `try_increment_share_link_solve_count` RPC, which does the check-and-increment
|
|
10
|
-
* in a single statement.
|
|
11
|
-
*
|
|
12
|
-
* This lives in the Supabase suite (not the shared conformance suite or the app
|
|
13
|
-
* route tests) because it is the ONLY backend that actually provides the
|
|
14
|
-
* guarantee: the local provider's whole-file read-modify-write is a documented
|
|
15
|
-
* dev-scale tradeoff and is not concurrency-safe. Skipped without a live stack,
|
|
16
|
-
* matching the other conformance tests here.
|
|
17
|
-
*
|
|
18
|
-
* Complements the sequential cap/count tests at
|
|
19
|
-
* `packages/selva/src/routes/api/compute/__tests__/solve-cap-and-count.test.ts`.
|
|
20
|
-
*/
|
|
21
|
-
import { describe, it, expect, beforeEach } from 'vitest';
|
|
22
|
-
import { SupabaseShareLinkStore } from '../SupabaseShareLinkStore.js';
|
|
23
|
-
import { readEnv, resetAllData, seedUser } from './test-helpers.js';
|
|
24
|
-
const envCtx = readEnv();
|
|
25
|
-
if (!envCtx) {
|
|
26
|
-
describe.skip('SupabaseShareLinkStore concurrency (skipped: no live stack)', () => {
|
|
27
|
-
it('populate packages/providers/supabase/.env.test with Supabase creds to run these tests', () => { });
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
else {
|
|
31
|
-
const ctx = { userId: '', system: true };
|
|
32
|
-
/** Seed org → project → definition → share link, all via service-role. */
|
|
33
|
-
async function seedCappedLink(maxSolves) {
|
|
34
|
-
const { userId: ownerId } = await seedUser(envCtx, '');
|
|
35
|
-
const admin = envCtx.adminClient;
|
|
36
|
-
const orgId = crypto.randomUUID();
|
|
37
|
-
const projectId = crypto.randomUUID();
|
|
38
|
-
const definitionId = crypto.randomUUID();
|
|
39
|
-
const linkId = crypto.randomUUID();
|
|
40
|
-
const now = new Date().toISOString();
|
|
41
|
-
const { error: orgErr } = await admin.from('orgs').insert({
|
|
42
|
-
id: orgId,
|
|
43
|
-
name: 'Concurrency Org',
|
|
44
|
-
slug: `conc-${orgId.slice(0, 8)}`,
|
|
45
|
-
owner_id: ownerId,
|
|
46
|
-
created_at: now,
|
|
47
|
-
updated_at: now
|
|
48
|
-
});
|
|
49
|
-
if (orgErr)
|
|
50
|
-
throw orgErr;
|
|
51
|
-
const { error: projErr } = await admin.from('projects').insert({
|
|
52
|
-
id: projectId,
|
|
53
|
-
org_id: orgId,
|
|
54
|
-
name: 'Project',
|
|
55
|
-
slug: `proj-${projectId.slice(0, 8)}`,
|
|
56
|
-
visibility: 'public',
|
|
57
|
-
owner_id: ownerId,
|
|
58
|
-
created_at: now,
|
|
59
|
-
updated_at: now
|
|
60
|
-
});
|
|
61
|
-
if (projErr)
|
|
62
|
-
throw projErr;
|
|
63
|
-
const { error: defErr } = await admin.from('definitions').insert({
|
|
64
|
-
guid: definitionId,
|
|
65
|
-
project_id: projectId,
|
|
66
|
-
owner_id: ownerId,
|
|
67
|
-
display_name: 'Def',
|
|
68
|
-
status: 'published',
|
|
69
|
-
created_at: now,
|
|
70
|
-
updated_at: now
|
|
71
|
-
});
|
|
72
|
-
if (defErr)
|
|
73
|
-
throw defErr;
|
|
74
|
-
const link = {
|
|
75
|
-
id: linkId,
|
|
76
|
-
definitionId,
|
|
77
|
-
channel: 'live',
|
|
78
|
-
tokenHash: crypto.randomUUID().replace(/-/g, ''),
|
|
79
|
-
createdBy: ownerId,
|
|
80
|
-
createdAt: now,
|
|
81
|
-
expiresAt: null,
|
|
82
|
-
revokedAt: null,
|
|
83
|
-
allowSolve: true,
|
|
84
|
-
maxSolves,
|
|
85
|
-
solveCount: 0
|
|
86
|
-
};
|
|
87
|
-
const store = new SupabaseShareLinkStore(envCtx.bundle);
|
|
88
|
-
await store.create(ctx, link);
|
|
89
|
-
return { linkId };
|
|
90
|
-
}
|
|
91
|
-
describe('SupabaseShareLinkStore — concurrent solve-cap enforcement', () => {
|
|
92
|
-
beforeEach(async () => {
|
|
93
|
-
await resetAllData(envCtx);
|
|
94
|
-
});
|
|
95
|
-
it('N concurrent solves against a cap-K link admit exactly K, refuse the rest', async () => {
|
|
96
|
-
const CAP = 5;
|
|
97
|
-
const ATTEMPTS = 25;
|
|
98
|
-
const { linkId } = await seedCappedLink(CAP);
|
|
99
|
-
const store = new SupabaseShareLinkStore(envCtx.bundle);
|
|
100
|
-
const outcomes = await Promise.all(Array.from({ length: ATTEMPTS }, () => store.tryIncrementSolveCount(ctx, linkId)));
|
|
101
|
-
const admitted = outcomes.filter((n) => n !== null);
|
|
102
|
-
const refused = outcomes.filter((n) => n === null);
|
|
103
|
-
// Exactly CAP admitted — the atomic RPC never lets a concurrent burst
|
|
104
|
-
// overshoot the cap.
|
|
105
|
-
expect(admitted).toHaveLength(CAP);
|
|
106
|
-
expect(refused).toHaveLength(ATTEMPTS - CAP);
|
|
107
|
-
// Each admitted solve got a distinct slot 1..CAP — no lost update.
|
|
108
|
-
expect([...admitted].sort((a, b) => a - b)).toEqual([1, 2, 3, 4, 5]);
|
|
109
|
-
// The persisted count settles at exactly the cap.
|
|
110
|
-
const finalLink = await store.getById(ctx, linkId);
|
|
111
|
-
expect(finalLink?.solveCount).toBe(CAP);
|
|
112
|
-
});
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
//# sourceMappingURL=share-link-concurrency.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"share-link-concurrency.test.js","sourceRoot":"","sources":["../../../src/data/__tests__/share-link-concurrency.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"share-link-conformance.test.d.ts","sourceRoot":"","sources":["../../../src/data/__tests__/share-link-conformance.test.ts"],"names":[],"mappings":""}
|