@selvajs/platform 0.14.2 → 0.14.3-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/computeServer/index.d.ts +2 -0
- package/dist/computeServer/index.d.ts.map +1 -1
- package/dist/computeServer/index.js +6 -0
- package/dist/computeServer/index.js.map +1 -1
- package/dist/computeServer/interface.d.ts +10 -0
- package/dist/computeServer/interface.d.ts.map +1 -1
- package/dist/computeServer/secrets.d.ts +53 -0
- package/dist/computeServer/secrets.d.ts.map +1 -0
- package/dist/computeServer/secrets.js +67 -0
- package/dist/computeServer/secrets.js.map +1 -0
- package/dist/context.d.ts +7 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +13 -0
- package/dist/context.js.map +1 -1
- package/dist/definitions/interface.d.ts +8 -0
- package/dist/definitions/interface.d.ts.map +1 -1
- package/dist/errors/interface.d.ts +44 -0
- package/dist/errors/interface.d.ts.map +1 -0
- package/dist/errors/interface.js +9 -0
- package/dist/errors/interface.js.map +1 -0
- package/dist/index.d.ts +11 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/organizations/index.d.ts +4 -3
- package/dist/organizations/index.d.ts.map +1 -1
- package/dist/organizations/index.js +2 -1
- package/dist/organizations/index.js.map +1 -1
- package/dist/organizations/interface.d.ts +1 -1
- package/dist/organizations/interface.d.ts.map +1 -1
- package/dist/organizations/paths.d.ts +22 -0
- package/dist/organizations/paths.d.ts.map +1 -0
- package/dist/organizations/paths.js +43 -0
- package/dist/organizations/paths.js.map +1 -0
- package/dist/organizations/schemas.d.ts +10 -0
- package/dist/organizations/schemas.d.ts.map +1 -1
- package/dist/organizations/schemas.js +6 -0
- package/dist/organizations/schemas.js.map +1 -1
- package/dist/organizations/types.d.ts +10 -1
- package/dist/organizations/types.d.ts.map +1 -1
- package/dist/storage/assetClasses.d.ts +59 -0
- package/dist/storage/assetClasses.d.ts.map +1 -0
- package/dist/storage/assetClasses.js +86 -0
- package/dist/storage/assetClasses.js.map +1 -0
- package/dist/storage/cacheBust.d.ts +21 -0
- package/dist/storage/cacheBust.d.ts.map +1 -0
- package/dist/storage/cacheBust.js +29 -0
- package/dist/storage/cacheBust.js.map +1 -0
- package/dist/storage/image.d.ts +6 -1
- package/dist/storage/image.d.ts.map +1 -1
- package/dist/storage/image.js +8 -3
- package/dist/storage/image.js.map +1 -1
- package/dist/storage/index.d.ts +3 -0
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +2 -0
- package/dist/storage/index.js.map +1 -1
- package/dist/testing/suites/definitionStoreSuite.d.ts.map +1 -1
- package/dist/testing/suites/definitionStoreSuite.js +30 -0
- package/dist/testing/suites/definitionStoreSuite.js.map +1 -1
- package/dist/testing/suites/orgStoreSuite.d.ts.map +1 -1
- package/dist/testing/suites/orgStoreSuite.js +12 -0
- package/dist/testing/suites/orgStoreSuite.js.map +1 -1
- package/dist/testing/suites/storageProviderSuite.d.ts.map +1 -1
- package/dist/testing/suites/storageProviderSuite.js +18 -0
- package/dist/testing/suites/storageProviderSuite.js.map +1 -1
- package/package.json +2 -2
- package/src/computeServer/index.ts +11 -0
- package/src/computeServer/interface.ts +11 -0
- package/src/computeServer/secrets.ts +102 -0
- package/src/context.ts +14 -0
- package/src/definitions/interface.ts +9 -0
- package/src/errors/interface.ts +45 -0
- package/src/index.ts +30 -2
- package/src/organizations/index.ts +11 -2
- package/src/organizations/interface.ts +1 -1
- package/src/organizations/paths.ts +45 -0
- package/src/organizations/schemas.ts +9 -0
- package/src/organizations/types.ts +11 -1
- package/src/storage/assetClasses.ts +134 -0
- package/src/storage/cacheBust.ts +26 -0
- package/src/storage/image.ts +8 -3
- package/src/storage/index.ts +3 -0
- package/src/testing/suites/definitionStoreSuite.ts +45 -0
- package/src/testing/suites/orgStoreSuite.ts +17 -0
- package/src/testing/suites/storageProviderSuite.ts +21 -0
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export type { ComputeServerConfig, ComputeConfig, PlatformComputeServer, OrgComputeServer } from './types.js';
|
|
2
2
|
export { isPlatformServer, isOrgServer } from './types.js';
|
|
3
3
|
export type { IComputeServerStore } from './interface.js';
|
|
4
|
+
export { isEncryptedSecret, encryptSecret, decryptSecret, decodeSecretKey } from './secrets.js';
|
|
5
|
+
export type { SecretVerificationReport, SecretVerificationFailure, SecretVerificationFailureReason } from './secrets.js';
|
|
4
6
|
export type { ResolveOptions } from './utils.js';
|
|
5
7
|
export { serversVisibleTo, defaultServerIdFor, resolveServerForOrg, findServerById, platformServers, orgServersFor } from './utils.js';
|
|
6
8
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/computeServer/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACX,mBAAmB,EACnB,aAAa,EACb,qBAAqB,EACrB,gBAAgB,EAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC3D,YAAY,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/computeServer/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACX,mBAAmB,EACnB,aAAa,EACb,qBAAqB,EACrB,gBAAgB,EAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC3D,YAAY,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAM1D,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAChG,YAAY,EACX,wBAAwB,EACxB,yBAAyB,EACzB,+BAA+B,EAC/B,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EACN,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,aAAa,EACb,MAAM,YAAY,CAAC"}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
1
|
export { isPlatformServer, isOrgServer } from './types.js';
|
|
2
|
+
// At-rest secret crypto (uses `node:crypto`). Server-only — deliberately NOT
|
|
3
|
+
// re-exported from the root barrel, which client `.svelte` code imports and
|
|
4
|
+
// where a browser bundle can't resolve `node:crypto`. Import these from
|
|
5
|
+
// `@selvajs/platform/computeServer` in server code. The report TYPES are erased
|
|
6
|
+
// at build, so they also stay re-exported from the root barrel for convenience.
|
|
7
|
+
export { isEncryptedSecret, encryptSecret, decryptSecret, decodeSecretKey } from './secrets.js';
|
|
2
8
|
export { serversVisibleTo, defaultServerIdFor, resolveServerForOrg, findServerById, platformServers, orgServersFor } from './utils.js';
|
|
3
9
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/computeServer/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/computeServer/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE3D,6EAA6E;AAC7E,4EAA4E;AAC5E,wEAAwE;AACxE,gFAAgF;AAChF,gFAAgF;AAChF,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAOhG,OAAO,EACN,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,aAAa,EACb,MAAM,YAAY,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { RequestContext } from '../context.js';
|
|
2
2
|
import type { ComputeConfig, ComputeServerConfig } from './types.js';
|
|
3
|
+
import type { SecretVerificationReport } from './secrets.js';
|
|
3
4
|
/**
|
|
4
5
|
* Compute-server configuration. Architecture spec §4.8.
|
|
5
6
|
*
|
|
@@ -45,5 +46,14 @@ export interface IComputeServerStore {
|
|
|
45
46
|
* compute config behind.
|
|
46
47
|
*/
|
|
47
48
|
deleteByOrg(ctx: RequestContext, orgId: string): Promise<void>;
|
|
49
|
+
/**
|
|
50
|
+
* Boot-time integrity check: attempt to decrypt every stored `apiKey` and
|
|
51
|
+
* report any that are plaintext-at-rest or fail to decrypt under the current
|
|
52
|
+
* `SELVA_AT_REST_KEY`. Does NOT throw — returns a structured report so the
|
|
53
|
+
* caller (boot health) decides whether to refuse boot / drive `/api/health`
|
|
54
|
+
* to 503. Both encrypting stores (local file, Supabase) implement this;
|
|
55
|
+
* optional so a hypothetical non-encrypting store can omit it.
|
|
56
|
+
*/
|
|
57
|
+
verifySecrets?(): Promise<SecretVerificationReport>;
|
|
48
58
|
}
|
|
49
59
|
//# sourceMappingURL=interface.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/computeServer/interface.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/computeServer/interface.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACrE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAE7D;;;;;;;;GAQG;AACH,MAAM,WAAW,mBAAmB;IACnC;;;;;OAKG;IACH,SAAS,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAEvD;;;OAGG;IACH,mBAAmB,CAClB,GAAG,EAAE,cAAc,EACnB,OAAO,EAAE,mBAAmB,EAAE,EAC9B,eAAe,EAAE,MAAM,GAAG,SAAS,GACjC,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB;;;;;;OAMG;IACH,cAAc,CACb,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,mBAAmB,EAAE,EAC9B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,GAC7B,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB;;;;;OAKG;IACH,aAAa,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1F;;;;;;OAMG;IACH,WAAW,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE/D;;;;;;;OAOG;IACH,aAAa,CAAC,IAAI,OAAO,CAAC,wBAAwB,CAAC,CAAC;CACpD"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AES-256-GCM envelope for at-rest secrets (e.g. compute API keys).
|
|
3
|
+
*
|
|
4
|
+
* Wire format: `enc:v1:<base64(iv|tag|ciphertext)>`. The version prefix lets
|
|
5
|
+
* us migrate to a new algorithm later without ambiguity. Plaintext never sits
|
|
6
|
+
* at rest — on disk (local provider) or in the DB (Supabase provider).
|
|
7
|
+
*
|
|
8
|
+
* Security model: defends against backup leaks, accidental file/DB sharing,
|
|
9
|
+
* and read-only storage access. An attacker with both the stored ciphertext
|
|
10
|
+
* *and* the master key (`SELVA_AT_REST_KEY` env var, process memory) can still
|
|
11
|
+
* decrypt — this is encryption at rest, not a secret manager.
|
|
12
|
+
*
|
|
13
|
+
* Provider-agnostic: pure `node:crypto`, no fs or DB coupling, so both the
|
|
14
|
+
* local and Supabase compute-server stores share this one implementation.
|
|
15
|
+
*/
|
|
16
|
+
export declare function isEncryptedSecret(value: string): boolean;
|
|
17
|
+
export declare function encryptSecret(plaintext: string, key: Buffer): string;
|
|
18
|
+
export declare function decryptSecret(envelope: string, key: Buffer): string;
|
|
19
|
+
/**
|
|
20
|
+
* Decode a `SELVA_AT_REST_KEY` env var into a 32-byte buffer. Accepts either
|
|
21
|
+
* 64-char hex or base64 (with or without padding). Throws on anything else
|
|
22
|
+
* so misconfiguration fails loudly at boot rather than silently producing
|
|
23
|
+
* an undecryptable value.
|
|
24
|
+
*/
|
|
25
|
+
export declare function decodeSecretKey(raw: string): Buffer;
|
|
26
|
+
/**
|
|
27
|
+
* Result of a compute-server store's `verifySecrets()`. One `failures` entry
|
|
28
|
+
* per server whose `apiKey` couldn't be loaded:
|
|
29
|
+
* - `plaintext_on_disk` — the field exists but isn't an `enc:v1:` envelope.
|
|
30
|
+
* Either a hand-edit, a legacy row from before encryption, or a migration
|
|
31
|
+
* regression. Security-relevant.
|
|
32
|
+
* - `key_mismatch` — envelope is valid but GCM auth-tag verification
|
|
33
|
+
* fails under the current `SELVA_AT_REST_KEY`. The key was rotated or the
|
|
34
|
+
* data came from another deployment.
|
|
35
|
+
*
|
|
36
|
+
* Storage-agnostic (`plaintext_on_disk` reads "plaintext at rest" for both the
|
|
37
|
+
* file- and DB-backed stores) so boot health can treat every provider alike.
|
|
38
|
+
*/
|
|
39
|
+
export type SecretVerificationFailureReason = 'key_mismatch' | 'plaintext_on_disk';
|
|
40
|
+
export interface SecretVerificationFailure {
|
|
41
|
+
serverId: string;
|
|
42
|
+
serverLabel: string;
|
|
43
|
+
reason: SecretVerificationFailureReason;
|
|
44
|
+
/** Underlying error message for `key_mismatch`. Absent for plaintext. */
|
|
45
|
+
cause?: string;
|
|
46
|
+
}
|
|
47
|
+
export interface SecretVerificationReport {
|
|
48
|
+
ok: boolean;
|
|
49
|
+
failures: SecretVerificationFailure[];
|
|
50
|
+
/** True if at least one row holds an unencrypted apiKey at rest. */
|
|
51
|
+
plaintextFound: boolean;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=secrets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secrets.d.ts","sourceRoot":"","sources":["../../src/computeServer/secrets.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;GAcG;AAEH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAYpE;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAcnE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAQnD;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,+BAA+B,GAAG,cAAc,GAAG,mBAAmB,CAAC;AAEnF,MAAM,WAAW,yBAAyB;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,+BAA+B,CAAC;IACxC,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,wBAAwB;IACxC,EAAE,EAAE,OAAO,CAAC;IACZ,QAAQ,EAAE,yBAAyB,EAAE,CAAC;IACtC,oEAAoE;IACpE,cAAc,EAAE,OAAO,CAAC;CACxB"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { randomBytes, createCipheriv, createDecipheriv } from 'node:crypto';
|
|
2
|
+
const ALGO = 'aes-256-gcm';
|
|
3
|
+
const IV_BYTES = 12;
|
|
4
|
+
const TAG_BYTES = 16;
|
|
5
|
+
const PREFIX = 'enc:v1:';
|
|
6
|
+
/**
|
|
7
|
+
* AES-256-GCM envelope for at-rest secrets (e.g. compute API keys).
|
|
8
|
+
*
|
|
9
|
+
* Wire format: `enc:v1:<base64(iv|tag|ciphertext)>`. The version prefix lets
|
|
10
|
+
* us migrate to a new algorithm later without ambiguity. Plaintext never sits
|
|
11
|
+
* at rest — on disk (local provider) or in the DB (Supabase provider).
|
|
12
|
+
*
|
|
13
|
+
* Security model: defends against backup leaks, accidental file/DB sharing,
|
|
14
|
+
* and read-only storage access. An attacker with both the stored ciphertext
|
|
15
|
+
* *and* the master key (`SELVA_AT_REST_KEY` env var, process memory) can still
|
|
16
|
+
* decrypt — this is encryption at rest, not a secret manager.
|
|
17
|
+
*
|
|
18
|
+
* Provider-agnostic: pure `node:crypto`, no fs or DB coupling, so both the
|
|
19
|
+
* local and Supabase compute-server stores share this one implementation.
|
|
20
|
+
*/
|
|
21
|
+
export function isEncryptedSecret(value) {
|
|
22
|
+
return value.startsWith(PREFIX);
|
|
23
|
+
}
|
|
24
|
+
export function encryptSecret(plaintext, key) {
|
|
25
|
+
if (key.length !== 32) {
|
|
26
|
+
throw new Error(`Secret key must be 32 bytes; got ${key.length}`);
|
|
27
|
+
}
|
|
28
|
+
if (isEncryptedSecret(plaintext)) {
|
|
29
|
+
throw new Error('Refusing to encrypt a value that is already encrypted');
|
|
30
|
+
}
|
|
31
|
+
const iv = randomBytes(IV_BYTES);
|
|
32
|
+
const cipher = createCipheriv(ALGO, key, iv);
|
|
33
|
+
const ciphertext = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);
|
|
34
|
+
const tag = cipher.getAuthTag();
|
|
35
|
+
return PREFIX + Buffer.concat([iv, tag, ciphertext]).toString('base64');
|
|
36
|
+
}
|
|
37
|
+
export function decryptSecret(envelope, key) {
|
|
38
|
+
if (key.length !== 32) {
|
|
39
|
+
throw new Error(`Secret key must be 32 bytes; got ${key.length}`);
|
|
40
|
+
}
|
|
41
|
+
if (!isEncryptedSecret(envelope)) {
|
|
42
|
+
throw new Error('Value is not an encrypted secret envelope');
|
|
43
|
+
}
|
|
44
|
+
const buf = Buffer.from(envelope.slice(PREFIX.length), 'base64');
|
|
45
|
+
const iv = buf.subarray(0, IV_BYTES);
|
|
46
|
+
const tag = buf.subarray(IV_BYTES, IV_BYTES + TAG_BYTES);
|
|
47
|
+
const ciphertext = buf.subarray(IV_BYTES + TAG_BYTES);
|
|
48
|
+
const decipher = createDecipheriv(ALGO, key, iv);
|
|
49
|
+
decipher.setAuthTag(tag);
|
|
50
|
+
return Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString('utf8');
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Decode a `SELVA_AT_REST_KEY` env var into a 32-byte buffer. Accepts either
|
|
54
|
+
* 64-char hex or base64 (with or without padding). Throws on anything else
|
|
55
|
+
* so misconfiguration fails loudly at boot rather than silently producing
|
|
56
|
+
* an undecryptable value.
|
|
57
|
+
*/
|
|
58
|
+
export function decodeSecretKey(raw) {
|
|
59
|
+
if (/^[0-9a-fA-F]{64}$/.test(raw))
|
|
60
|
+
return Buffer.from(raw, 'hex');
|
|
61
|
+
const buf = Buffer.from(raw, 'base64');
|
|
62
|
+
if (buf.length === 32)
|
|
63
|
+
return buf;
|
|
64
|
+
throw new Error('SELVA_AT_REST_KEY must be 32 bytes encoded as 64-char hex or base64. ' +
|
|
65
|
+
"Generate one with: node -e \"console.log(require('crypto').randomBytes(32).toString('hex'))\"");
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=secrets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secrets.js","sourceRoot":"","sources":["../../src/computeServer/secrets.ts"],"names":[],"mappings":"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"}
|
package/dist/context.d.ts
CHANGED
|
@@ -38,4 +38,11 @@ export declare const SYSTEM_CONTEXT: RequestContext;
|
|
|
38
38
|
* `actingOrgId` returns false unless `instance_admin` or `system`.
|
|
39
39
|
*/
|
|
40
40
|
export declare function hasPermission(ctx: RequestContext, permission: PlatformPermission | OrgPermission): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Return the org the caller is acting as, or throw `ProviderError(403)` when
|
|
43
|
+
* the context has none. Stores that scope every row to an acting org repeat
|
|
44
|
+
* this guard; centralizing it keeps the failure a single, consistent 403
|
|
45
|
+
* rather than a `null` that leaks into a query as `org_id = undefined`.
|
|
46
|
+
*/
|
|
47
|
+
export declare function requireActingOrg(ctx: RequestContext): string;
|
|
41
48
|
//# sourceMappingURL=context.d.ts.map
|
package/dist/context.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAIhE;;;;;;;;;;GAUG;AACH,MAAM,WAAW,cAAc;IAC9B,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,oEAAoE;IACpE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,kBAAkB,EAAE,CAAC;IAC1C,6CAA6C;IAC7C,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,wCAAwC;IACxC,MAAM,CAAC,EAAE,IAAI,CAAC;IACd;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,cAK5B,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,aAAa,CAC5B,GAAG,EAAE,cAAc,EACnB,UAAU,EAAE,kBAAkB,GAAG,aAAa,GAC5C,OAAO,CAOT;AAQD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,CAK5D"}
|
package/dist/context.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ALL_PLATFORM_PERMISSIONS } from './permissions/types.js';
|
|
2
2
|
import { ALL_ORG_PERMISSIONS } from './organizations/schemas.js';
|
|
3
|
+
import { ProviderError } from './errors.js';
|
|
3
4
|
/**
|
|
4
5
|
* For server-internal operations outside any HTTP request (bootstrap,
|
|
5
6
|
* janitors, migrations). Treated as fully authorized.
|
|
@@ -29,4 +30,16 @@ const PLATFORM_PERMISSION_VALUES = new Set(ALL_PLATFORM_PERMISSIONS);
|
|
|
29
30
|
function isPlatformPermission(p) {
|
|
30
31
|
return PLATFORM_PERMISSION_VALUES.has(p);
|
|
31
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Return the org the caller is acting as, or throw `ProviderError(403)` when
|
|
35
|
+
* the context has none. Stores that scope every row to an acting org repeat
|
|
36
|
+
* this guard; centralizing it keeps the failure a single, consistent 403
|
|
37
|
+
* rather than a `null` that leaks into a query as `org_id = undefined`.
|
|
38
|
+
*/
|
|
39
|
+
export function requireActingOrg(ctx) {
|
|
40
|
+
if (!ctx.actingOrgId) {
|
|
41
|
+
throw new ProviderError('No acting organization in context', 403);
|
|
42
|
+
}
|
|
43
|
+
return ctx.actingOrgId;
|
|
44
|
+
}
|
|
32
45
|
//# sourceMappingURL=context.js.map
|
package/dist/context.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAElE,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAElE,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AA8B5C;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAmB;IAC7C,MAAM,EAAE,EAAE;IACV,mBAAmB,EAAE,CAAC,GAAG,wBAAwB,CAAC;IAClD,cAAc,EAAE,CAAC,GAAG,mBAAmB,CAAC;IACxC,MAAM,EAAE,IAAI;CACZ,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC5B,GAAmB,EACnB,UAA8C;IAE9C,IAAI,GAAG,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAC5B,IAAI,GAAG,CAAC,mBAAmB,CAAC,QAAQ,CAAC,gBAAgB,CAAC;QAAE,OAAO,IAAI,CAAC;IACpE,IAAI,oBAAoB,CAAC,UAAU,CAAC,EAAE,CAAC;QACtC,OAAO,GAAG,CAAC,mBAAmB,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,GAAG,CAAC,cAAc,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,0BAA0B,GAAG,IAAI,GAAG,CAAS,wBAAwB,CAAC,CAAC;AAE7E,SAAS,oBAAoB,CAAC,CAAS;IACtC,OAAO,0BAA0B,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAmB;IACnD,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;QACtB,MAAM,IAAI,aAAa,CAAC,mCAAmC,EAAE,GAAG,CAAC,CAAC;IACnE,CAAC;IACD,OAAO,GAAG,CAAC,WAAW,CAAC;AACxB,CAAC"}
|
|
@@ -22,6 +22,14 @@ export interface IDefinitionStore {
|
|
|
22
22
|
create(ctx: RequestContext, record: DefinitionRecord): Promise<void>;
|
|
23
23
|
update(ctx: RequestContext, guid: string, patch: DefinitionRecordPatch): Promise<void>;
|
|
24
24
|
delete(ctx: RequestContext, guid: string): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Cascade hook: soft-delete every live definition in a project. Called by
|
|
27
|
+
* `IProjectStore.deleteProject` — a deleted project must never keep serving
|
|
28
|
+
* its definitions (they surface in the library/public listings independent
|
|
29
|
+
* of the project row). No-op when the project has none. Mirrors the
|
|
30
|
+
* `deleteByProject` cascade hooks on `IPlatformProjectGrantStore`.
|
|
31
|
+
*/
|
|
32
|
+
deleteByProject(ctx: RequestContext, projectId: string): Promise<void>;
|
|
25
33
|
/** Atomic +1 on the solve counter. No-op if the record doesn't exist. */
|
|
26
34
|
incrementSolveCount(ctx: RequestContext, guid: string): Promise<void>;
|
|
27
35
|
createVersion(ctx: RequestContext, version: DefinitionVersion): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/definitions/interface.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACjF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE7F;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAEhC,IAAI,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;IACzF,aAAa,CACZ,GAAG,EAAE,cAAc,EACnB,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,qBAAqB,GAC1B,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;IACnC;;;;OAIG;IACH,UAAU,CACT,GAAG,EAAE,cAAc,EACnB,IAAI,CAAC,EAAE,qBAAqB,GAAG;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAC/C,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;IACnC,GAAG,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IACzE,MAAM,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrE,MAAM,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvF,MAAM,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzD,yEAAyE;IACzE,mBAAmB,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAGtE,aAAa,CAAC,GAAG,EAAE,cAAc,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,uCAAuC;IACvC,YAAY,CACX,GAAG,EAAE,cAAc,EACnB,YAAY,EAAE,MAAM,EACpB,IAAI,CAAC,EAAE,WAAW,GAChB,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC;IACpC,UAAU,CAAC,GAAG,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;IAEtF;;;;;OAKG;IACH,gBAAgB,CAAC,GAAG,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1F;;;OAGG;IACH,aAAa,CAAC,GAAG,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAErE,+EAA+E;IAC/E,cAAc,CAAC,GAAG,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5F,eAAe,CAAC,GAAG,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7F;;;;;;;;;;;;;OAaG;IACH,oBAAoB,CAAC,GAAG,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClG"}
|
|
1
|
+
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/definitions/interface.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured context attached to a reported error. All fields optional — a
|
|
3
|
+
* report can fire before any request context is built (e.g. an
|
|
4
|
+
* `unhandledRejection` with no active request). Deliberately NOT a
|
|
5
|
+
* `RequestContext`: reporters must never receive the opaque `authToken`, so
|
|
6
|
+
* only non-sensitive routing/identity fields are surfaced here.
|
|
7
|
+
*/
|
|
8
|
+
export interface ErrorContext {
|
|
9
|
+
/** HTTP method, when the error happened inside a request. */
|
|
10
|
+
method?: string;
|
|
11
|
+
/** Route pathname (never the query string — it can carry share tokens). */
|
|
12
|
+
route?: string;
|
|
13
|
+
/** Acting user id, when known. */
|
|
14
|
+
userId?: string;
|
|
15
|
+
/** Org the user was acting as, when known. */
|
|
16
|
+
orgId?: string;
|
|
17
|
+
/** Non-sensitive tags for grouping/search in the backend. */
|
|
18
|
+
tags?: Record<string, string>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Sink for unexpected server errors. Called from `handleError` and the
|
|
22
|
+
* process-level `unhandledRejection`/`uncaughtException` hooks.
|
|
23
|
+
*
|
|
24
|
+
* MUST NOT throw — reporting is best-effort and sits on the error path, where a
|
|
25
|
+
* second failure would mask the first. Implementations catch and log their own
|
|
26
|
+
* failures. MAY be fire-and-forget.
|
|
27
|
+
*/
|
|
28
|
+
export interface IErrorReporter {
|
|
29
|
+
/**
|
|
30
|
+
* Report an unexpected error. `error` is whatever was thrown/rejected —
|
|
31
|
+
* often an `Error`, but adapters occasionally reject with a plain object,
|
|
32
|
+
* so implementations must render defensively.
|
|
33
|
+
*/
|
|
34
|
+
capture(error: unknown, context?: ErrorContext): void;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Default `IErrorReporter` — discards every report. Used when no error-tracking
|
|
38
|
+
* backend is configured (e.g. `SENTRY_DSN` unset), so call sites can report
|
|
39
|
+
* unconditionally. Swap in a real reporter to ship errors off-box.
|
|
40
|
+
*/
|
|
41
|
+
export declare class NoopErrorReporter implements IErrorReporter {
|
|
42
|
+
capture(_error: unknown, _context?: ErrorContext): void;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=interface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/errors/interface.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC5B,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC9B;;;;OAIG;IACH,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;CACtD;AAED;;;;GAIG;AACH,qBAAa,iBAAkB,YAAW,cAAc;IACvD,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,YAAY,GAAG,IAAI;CACvD"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default `IErrorReporter` — discards every report. Used when no error-tracking
|
|
3
|
+
* backend is configured (e.g. `SENTRY_DSN` unset), so call sites can report
|
|
4
|
+
* unconditionally. Swap in a real reporter to ship errors off-box.
|
|
5
|
+
*/
|
|
6
|
+
export class NoopErrorReporter {
|
|
7
|
+
capture(_error, _context) { }
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=interface.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interface.js","sourceRoot":"","sources":["../../src/errors/interface.ts"],"names":[],"mappings":"AAqCA;;;;GAIG;AACH,MAAM,OAAO,iBAAiB;IAC7B,OAAO,CAAC,MAAe,EAAE,QAAuB,IAAS,CAAC;CAC1D"}
|
package/dist/index.d.ts
CHANGED
|
@@ -6,10 +6,11 @@ export type { IPlatformPermissionStore } from './permissions/interface.js';
|
|
|
6
6
|
export type { IUserProfileStore } from './userProfile/interface.js';
|
|
7
7
|
export type { UserProfile, RecentRun } from './userProfile/types.js';
|
|
8
8
|
export { emptyProfile } from './userProfile/types.js';
|
|
9
|
-
export type { Organization, OrgMember } from './organizations/types.js';
|
|
9
|
+
export type { Organization, OrgMember, OrgAssets } from './organizations/types.js';
|
|
10
10
|
export type { IOrgStore } from './organizations/interface.js';
|
|
11
|
-
export
|
|
12
|
-
export {
|
|
11
|
+
export { orgPaths } from './organizations/paths.js';
|
|
12
|
+
export type { OrgRole, OrgPermission, OrgAssetKind, CreateOrgInput, UpdateOrgInput } from './organizations/schemas.js';
|
|
13
|
+
export { OrgRoleSchema, OrgPermissionSchema, OrgAssetKindSchema, ALL_ORG_ASSET_KINDS, SlugSchema, CreateOrgSchema, UpdateOrgSchema, ALL_ORG_PERMISSIONS, DEFAULT_ORG_PERMISSIONS, OWNER_ADMIN_ONLY_PERMISSIONS, MEMBER_ASSIGNABLE_PERMISSIONS } from './organizations/schemas.js';
|
|
13
14
|
export type { Invite } from './invites/types.js';
|
|
14
15
|
export type { IInviteStore } from './invites/interface.js';
|
|
15
16
|
export type { Project, ProjectMember } from './projects/types.js';
|
|
@@ -34,10 +35,14 @@ export { CreateShareLinkInputSchema } from './shareLinks/schemas.js';
|
|
|
34
35
|
export type { IStorageProvider } from './storage/interface.js';
|
|
35
36
|
export { IMAGE_MAX_WIDTH, IMAGE_WEBP_QUALITY, isImageUpload, toWebpPath, transcodeImageIfNeeded } from './storage/image.js';
|
|
36
37
|
export type { TranscodeResult } from './storage/image.js';
|
|
38
|
+
export { ASSET_CLASSES, classifyAssetPath, isPublicAssetPath } from './storage/assetClasses.js';
|
|
39
|
+
export type { AssetVisibility, AssetScope, AssetClass, AssetMatch } from './storage/assetClasses.js';
|
|
40
|
+
export { withCacheBust } from './storage/cacheBust.js';
|
|
37
41
|
export type { IDataProvider } from './data/interface.js';
|
|
38
42
|
export type { ComputeServerConfig, ComputeConfig, PlatformComputeServer, OrgComputeServer } from './computeServer/types.js';
|
|
39
43
|
export { isPlatformServer, isOrgServer } from './computeServer/types.js';
|
|
40
44
|
export type { IComputeServerStore } from './computeServer/interface.js';
|
|
45
|
+
export type { SecretVerificationReport, SecretVerificationFailure, SecretVerificationFailureReason } from './computeServer/secrets.js';
|
|
41
46
|
export type { ResolveOptions } from './computeServer/utils.js';
|
|
42
47
|
export { serversVisibleTo, defaultServerIdFor, resolveServerForOrg, findServerById, platformServers, orgServersFor } from './computeServer/utils.js';
|
|
43
48
|
export type { ProjectAccessInput, DefinitionAccessInput, VisibilityChangeInput, ReclaimAccessInput, CreateProjectAccessInput, OwnerRemovalInput, OwnerRemovalCheck } from './access/rules.js';
|
|
@@ -47,12 +52,14 @@ export { actorFrom, NoopEventSink } from './events/interface.js';
|
|
|
47
52
|
export type { AuditEventRow, AuditCursor, AuditQueryFilters, AuditQueryResult, IAuditQuery } from './events/audit.js';
|
|
48
53
|
export type { ISolveMetricSink, SolveMetric, SolveFailureKind } from './metrics/interface.js';
|
|
49
54
|
export { NoopSolveMetricSink } from './metrics/interface.js';
|
|
55
|
+
export type { IErrorReporter, ErrorContext } from './errors/interface.js';
|
|
56
|
+
export { NoopErrorReporter } from './errors/interface.js';
|
|
50
57
|
export type { IBindingResolver } from './bindings/interface.js';
|
|
51
58
|
export { NoopBindingResolver } from './bindings/interface.js';
|
|
52
59
|
export type { AuditUpdate, AuditSoftDelete } from './utils/audit.js';
|
|
53
60
|
export { auditUpdate, auditSoftDelete } from './utils/audit.js';
|
|
54
61
|
export type { RequestContext } from './context.js';
|
|
55
|
-
export { SYSTEM_CONTEXT, hasPermission } from './context.js';
|
|
62
|
+
export { SYSTEM_CONTEXT, hasPermission, requireActingOrg } from './context.js';
|
|
56
63
|
export type { ListOptions, DefinitionListOptions, Page } from './pagination.js';
|
|
57
64
|
export { DEFAULT_PAGE_LIMIT, MAX_PAGE_LIMIT } from './pagination.js';
|
|
58
65
|
export type { TenancyMode, SelvaFlags, SelvaBranding, SelvaConfig, SelvaConfigFactory } from './config.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,YAAY,EAAE,QAAQ,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACnF,YAAY,EACX,aAAa,EACb,UAAU,EACV,aAAa,EACb,cAAc,EACd,UAAU,EACV,MAAM,qBAAqB,CAAC;AAK7B,YAAY,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAC5F,YAAY,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAG3E,YAAY,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACpE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAGtD,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,YAAY,EAAE,QAAQ,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACnF,YAAY,EACX,aAAa,EACb,UAAU,EACV,aAAa,EACb,cAAc,EACd,UAAU,EACV,MAAM,qBAAqB,CAAC;AAK7B,YAAY,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAC5F,YAAY,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAG3E,YAAY,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACpE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAGtD,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACnF,YAAY,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,YAAY,EACX,OAAO,EACP,aAAa,EACb,YAAY,EACZ,cAAc,EACd,cAAc,EACd,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACN,aAAa,EACb,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,UAAU,EACV,eAAe,EACf,eAAe,EACf,mBAAmB,EACnB,uBAAuB,EACvB,4BAA4B,EAC5B,6BAA6B,EAC7B,MAAM,4BAA4B,CAAC;AAGpC,YAAY,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAG3D,YAAY,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAClE,YAAY,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,YAAY,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAC5E,OAAO,EACN,uBAAuB,EACvB,iBAAiB,EACjB,oBAAoB,EACpB,MAAM,uBAAuB,CAAC;AAG/B,YAAY,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACpG,YAAY,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAClF,OAAO,EACN,0BAA0B,EAC1B,gCAAgC,EAChC,MAAM,+BAA+B,CAAC;AAGvC,YAAY,EACX,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACnE,YAAY,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EACN,aAAa,EACb,sBAAsB,EACtB,yBAAyB,EACzB,yBAAyB,EACzB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,YAAY,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EACN,uBAAuB,EACvB,yBAAyB,EACzB,2BAA2B,EAC3B,yBAAyB,EACzB,UAAU,EACV,UAAU,EACV,MAAM,0BAA0B,CAAC;AAKlC,YAAY,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,YAAY,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,6BAA6B,EAAE,MAAM,uBAAuB,CAAC;AACtE,YAAY,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AAKrE,YAAY,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EACN,eAAe,EACf,kBAAkB,EAClB,aAAa,EACb,UAAU,EACV,sBAAsB,EACtB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAChG,YAAY,EACX,eAAe,EACf,UAAU,EACV,UAAU,EACV,UAAU,EACV,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAKvD,YAAY,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAKzD,YAAY,EACX,mBAAmB,EACnB,aAAa,EACb,qBAAqB,EACrB,gBAAgB,EAChB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACzE,YAAY,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAMxE,YAAY,EACX,wBAAwB,EACxB,yBAAyB,EACzB,+BAA+B,EAC/B,MAAM,4BAA4B,CAAC;AACpC,YAAY,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EACN,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,aAAa,EACb,MAAM,0BAA0B,CAAC;AAKlC,YAAY,EACX,kBAAkB,EAClB,qBAAqB,EACrB,qBAAqB,EACrB,kBAAkB,EAClB,wBAAwB,EACxB,iBAAiB,EACjB,iBAAiB,EACjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACN,OAAO,EACP,QAAQ,EACR,OAAO,EACP,SAAS,EACT,sBAAsB,EACtB,2BAA2B,EAC3B,iBAAiB,EACjB,UAAU,EACV,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,MAAM,mBAAmB,CAAC;AAK3B,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACtF,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACjE,YAAY,EACX,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EAChB,WAAW,EACX,MAAM,mBAAmB,CAAC;AAK3B,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC9F,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAK7D,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAK1D,YAAY,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAK9D,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAKhE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAE/E,YAAY,EAAE,WAAW,EAAE,qBAAqB,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAChF,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAErE,YAAY,EACX,WAAW,EACX,UAAU,EACV,aAAa,EACb,WAAW,EACX,kBAAkB,EAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE1D,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// @selvajs/platform — published API contract. Every symbol here is breaking-change-protected.
|
|
2
2
|
export { PlatformPermissionSchema, ALL_PLATFORM_PERMISSIONS } from './permissions/types.js';
|
|
3
3
|
export { emptyProfile } from './userProfile/types.js';
|
|
4
|
-
export {
|
|
4
|
+
export { orgPaths } from './organizations/paths.js';
|
|
5
|
+
export { OrgRoleSchema, OrgPermissionSchema, OrgAssetKindSchema, ALL_ORG_ASSET_KINDS, SlugSchema, CreateOrgSchema, UpdateOrgSchema, ALL_ORG_PERMISSIONS, DEFAULT_ORG_PERMISSIONS, OWNER_ADMIN_ONLY_PERMISSIONS, MEMBER_ASSIGNABLE_PERMISSIONS } from './organizations/schemas.js';
|
|
5
6
|
export { ProjectVisibilitySchema, ProjectRoleSchema, validateProjectFlags } from './projects/schemas.js';
|
|
6
7
|
export { PlatformProjectGrantSchema, PlatformProjectGranteeTypeSchema } from './platformProjects/schemas.js';
|
|
7
8
|
export { GH_EXTENSIONS, COVER_IMAGE_EXTENSIONS, ALLOWED_UPLOAD_EXTENSIONS, COVER_IMAGE_CONTENT_TYPES } from './definitions/types.js';
|
|
@@ -10,14 +11,17 @@ export { DefinitionChannelSchema, PublishVersionInputSchema, CreateDefinitionInp
|
|
|
10
11
|
export { DEFAULT_SHARE_LINK_MAX_SOLVES } from './shareLinks/types.js';
|
|
11
12
|
export { CreateShareLinkInputSchema } from './shareLinks/schemas.js';
|
|
12
13
|
export { IMAGE_MAX_WIDTH, IMAGE_WEBP_QUALITY, isImageUpload, toWebpPath, transcodeImageIfNeeded } from './storage/image.js';
|
|
14
|
+
export { ASSET_CLASSES, classifyAssetPath, isPublicAssetPath } from './storage/assetClasses.js';
|
|
15
|
+
export { withCacheBust } from './storage/cacheBust.js';
|
|
13
16
|
export { isPlatformServer, isOrgServer } from './computeServer/types.js';
|
|
14
17
|
export { serversVisibleTo, defaultServerIdFor, resolveServerForOrg, findServerById, platformServers, orgServersFor } from './computeServer/utils.js';
|
|
15
18
|
export { canView, canSolve, canEdit, canManage, canEditProjectSettings, canChangeVisibilityToPublic, canEditDefinition, canReclaim, canCreateProject, checkOwnerRemoval, withAdminBypass } from './access/rules.js';
|
|
16
19
|
export { actorFrom, NoopEventSink } from './events/interface.js';
|
|
17
20
|
export { NoopSolveMetricSink } from './metrics/interface.js';
|
|
21
|
+
export { NoopErrorReporter } from './errors/interface.js';
|
|
18
22
|
export { NoopBindingResolver } from './bindings/interface.js';
|
|
19
23
|
export { auditUpdate, auditSoftDelete } from './utils/audit.js';
|
|
20
|
-
export { SYSTEM_CONTEXT, hasPermission } from './context.js';
|
|
24
|
+
export { SYSTEM_CONTEXT, hasPermission, requireActingOrg } from './context.js';
|
|
21
25
|
export { DEFAULT_PAGE_LIMIT, MAX_PAGE_LIMIT } from './pagination.js';
|
|
22
26
|
export { isFlagEnabled, defineConfig } from './config.js';
|
|
23
27
|
export { ProviderError } from './errors.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAgB9F,OAAO,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAM5F,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAgB9F,OAAO,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAM5F,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAKtD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAQpD,OAAO,EACN,aAAa,EACb,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,UAAU,EACV,eAAe,EACf,eAAe,EACf,mBAAmB,EACnB,uBAAuB,EACvB,4BAA4B,EAC5B,6BAA6B,EAC7B,MAAM,4BAA4B,CAAC;AAUpC,OAAO,EACN,uBAAuB,EACvB,iBAAiB,EACjB,oBAAoB,EACpB,MAAM,uBAAuB,CAAC;AAK/B,OAAO,EACN,0BAA0B,EAC1B,gCAAgC,EAChC,MAAM,+BAA+B,CAAC;AAavC,OAAO,EACN,aAAa,EACb,sBAAsB,EACtB,yBAAyB,EACzB,yBAAyB,EACzB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,OAAO,EACN,uBAAuB,EACvB,yBAAyB,EACzB,2BAA2B,EAC3B,yBAAyB,EACzB,UAAU,EACV,UAAU,EACV,MAAM,0BAA0B,CAAC;AAOlC,OAAO,EAAE,6BAA6B,EAAE,MAAM,uBAAuB,CAAC;AAEtE,OAAO,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AAMrE,OAAO,EACN,eAAe,EACf,kBAAkB,EAClB,aAAa,EACb,UAAU,EACV,sBAAsB,EACtB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAOhG,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAgBvD,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAazE,OAAO,EACN,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,aAAa,EACb,MAAM,0BAA0B,CAAC;AAclC,OAAO,EACN,OAAO,EACP,QAAQ,EACR,OAAO,EACP,SAAS,EACT,sBAAsB,EACtB,2BAA2B,EAC3B,iBAAiB,EACjB,UAAU,EACV,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,MAAM,mBAAmB,CAAC;AAM3B,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAajE,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAM7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAM1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAM9D,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAMhE,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAG/E,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AASrE,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE1D,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export type { Organization, OrgMember } from './types.js';
|
|
1
|
+
export type { Organization, OrgMember, OrgAssets } from './types.js';
|
|
2
2
|
export type { IOrgStore } from './interface.js';
|
|
3
|
-
export
|
|
4
|
-
export {
|
|
3
|
+
export { orgPaths } from './paths.js';
|
|
4
|
+
export type { OrgRole, OrgPermission, OrgAssetKind, CreateOrgInput, UpdateOrgInput } from './schemas.js';
|
|
5
|
+
export { OrgRoleSchema, OrgPermissionSchema, OrgAssetKindSchema, ALL_ORG_ASSET_KINDS, SlugSchema, CreateOrgSchema, UpdateOrgSchema, ALL_ORG_PERMISSIONS, DEFAULT_ORG_PERMISSIONS, OWNER_ADMIN_ONLY_PERMISSIONS, MEMBER_ASSIGNABLE_PERMISSIONS } from './schemas.js';
|
|
5
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/organizations/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/organizations/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACrE,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EACX,OAAO,EACP,aAAa,EACb,YAAY,EACZ,cAAc,EACd,cAAc,EACd,MAAM,cAAc,CAAC;AACtB,OAAO,EACN,aAAa,EACb,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,UAAU,EACV,eAAe,EACf,eAAe,EACf,mBAAmB,EACnB,uBAAuB,EACvB,4BAA4B,EAC5B,6BAA6B,EAC7B,MAAM,cAAc,CAAC"}
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { orgPaths } from './paths.js';
|
|
2
|
+
export { OrgRoleSchema, OrgPermissionSchema, OrgAssetKindSchema, ALL_ORG_ASSET_KINDS, SlugSchema, CreateOrgSchema, UpdateOrgSchema, ALL_ORG_PERMISSIONS, DEFAULT_ORG_PERMISSIONS, OWNER_ADMIN_ONLY_PERMISSIONS, MEMBER_ASSIGNABLE_PERMISSIONS } from './schemas.js';
|
|
2
3
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/organizations/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/organizations/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAQtC,OAAO,EACN,aAAa,EACb,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,UAAU,EACV,eAAe,EACf,eAAe,EACf,mBAAmB,EACnB,uBAAuB,EACvB,4BAA4B,EAC5B,6BAA6B,EAC7B,MAAM,cAAc,CAAC"}
|
|
@@ -11,7 +11,7 @@ export interface IOrgStore {
|
|
|
11
11
|
getOrg(ctx: RequestContext, id: string): Promise<Organization | null>;
|
|
12
12
|
getOrgBySlug(ctx: RequestContext, slug: string): Promise<Organization | null>;
|
|
13
13
|
createOrg(ctx: RequestContext, org: Organization): Promise<void>;
|
|
14
|
-
updateOrg(ctx: RequestContext, id: string, patch: Partial<Pick<Organization, 'name' | 'slug'>>): Promise<void>;
|
|
14
|
+
updateOrg(ctx: RequestContext, id: string, patch: Partial<Pick<Organization, 'name' | 'slug' | 'assets'>>): Promise<void>;
|
|
15
15
|
/**
|
|
16
16
|
* Soft-delete the org. Cascades soft-delete to org members, projects in the
|
|
17
17
|
* org, and project members. Definitions and share links cascade through the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/organizations/interface.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE3D;;;GAGG;AACH,MAAM,WAAW,SAAS;IAEzB,QAAQ,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;IAC/E,MAAM,CAAC,GAAG,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IACtE,YAAY,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAC9E,SAAS,CAAC,GAAG,EAAE,cAAc,EAAE,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,SAAS,CACR,GAAG,EAAE,cAAc,EACnB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/organizations/interface.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE3D;;;GAGG;AACH,MAAM,WAAW,SAAS;IAEzB,QAAQ,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;IAC/E,MAAM,CAAC,GAAG,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IACtE,YAAY,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAC9E,SAAS,CAAC,GAAG,EAAE,cAAc,EAAE,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,SAAS,CACR,GAAG,EAAE,cAAc,EACnB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC,CAAC,GAC5D,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB;;;;;OAKG;IACH,SAAS,CAAC,GAAG,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAG1D,cAAc,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IACjG,YAAY,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IAC5F;;;;;;;;;;;;OAYG;IACH,kBAAkB,CACjB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,MAAM,GACZ,OAAO,CAAC;QAAE,GAAG,EAAE,YAAY,CAAC;QAAC,MAAM,EAAE,SAAS,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IAC5D,YAAY,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,mBAAmB,CAClB,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,GACX,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB;;;;OAIG;IACH,0BAA0B,CACzB,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,SAAS,aAAa,EAAE,GACnC,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,eAAe,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnF"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { OrgAssetKind } from './schemas.js';
|
|
2
|
+
/**
|
|
3
|
+
* Storage keys for org-scoped assets. Every branding asset is stored as `.webp`
|
|
4
|
+
* (uploads are rasterized through the shared transcoder), so the path per kind
|
|
5
|
+
* is fixed — a re-upload overwrites in place via `IStorageProvider.put`'s
|
|
6
|
+
* upsert. The filename IS the kind, so the layout is generic: a new branding
|
|
7
|
+
* kind needs no new helper.
|
|
8
|
+
*
|
|
9
|
+
* Branding lives under `orgs/{id}/branding/` because it is a *public* asset
|
|
10
|
+
* class — anyone, incl. logged-out viewers, may read a company logo. The
|
|
11
|
+
* `branding/` segment keeps it distinguishable from future org-private blobs
|
|
12
|
+
* under `orgs/{id}/private/` (e.g. pricing sheets), which are members-only.
|
|
13
|
+
* The serving route and `getPublicUrl` decide public-vs-private by classifying
|
|
14
|
+
* these prefixes — see `classifyAssetPath` / `ASSET_CLASSES`.
|
|
15
|
+
*/
|
|
16
|
+
export declare const orgPaths: {
|
|
17
|
+
readonly asset: (id: string, kind: OrgAssetKind) => string;
|
|
18
|
+
/** Members-only blob under the org's private tier. `name` includes the extension. */
|
|
19
|
+
readonly privateAsset: (id: string, name: string) => string;
|
|
20
|
+
readonly prefix: (id: string) => string;
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/organizations/paths.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAcjD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,QAAQ;yBACR,MAAM,QAAQ,YAAY;IAKtC,qFAAqF;gCAClE,MAAM,QAAQ,MAAM;0BAK1B,MAAM;CAIV,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path-segment safety check. Blocks traversal, separators, NUL, and empty
|
|
3
|
+
* segments. Allowed alphabet `[A-Za-z0-9._-]+` covers GUIDs and sanitized
|
|
4
|
+
* refs. Called by every helper so a malicious `id` can't escape the
|
|
5
|
+
* `orgs/` prefix. Mirrors `definitionPaths`' guard.
|
|
6
|
+
*/
|
|
7
|
+
function assertSafeKey(value, label) {
|
|
8
|
+
if (!value || !/^[A-Za-z0-9._-]+$/.test(value) || value === '.' || value === '..') {
|
|
9
|
+
throw new Error(`Unsafe ${label}: ${JSON.stringify(value)}`);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Storage keys for org-scoped assets. Every branding asset is stored as `.webp`
|
|
14
|
+
* (uploads are rasterized through the shared transcoder), so the path per kind
|
|
15
|
+
* is fixed — a re-upload overwrites in place via `IStorageProvider.put`'s
|
|
16
|
+
* upsert. The filename IS the kind, so the layout is generic: a new branding
|
|
17
|
+
* kind needs no new helper.
|
|
18
|
+
*
|
|
19
|
+
* Branding lives under `orgs/{id}/branding/` because it is a *public* asset
|
|
20
|
+
* class — anyone, incl. logged-out viewers, may read a company logo. The
|
|
21
|
+
* `branding/` segment keeps it distinguishable from future org-private blobs
|
|
22
|
+
* under `orgs/{id}/private/` (e.g. pricing sheets), which are members-only.
|
|
23
|
+
* The serving route and `getPublicUrl` decide public-vs-private by classifying
|
|
24
|
+
* these prefixes — see `classifyAssetPath` / `ASSET_CLASSES`.
|
|
25
|
+
*/
|
|
26
|
+
export const orgPaths = {
|
|
27
|
+
asset: (id, kind) => {
|
|
28
|
+
assertSafeKey(id, 'orgId');
|
|
29
|
+
assertSafeKey(kind, 'assetKind');
|
|
30
|
+
return `orgs/${id}/branding/${kind}.webp`;
|
|
31
|
+
},
|
|
32
|
+
/** Members-only blob under the org's private tier. `name` includes the extension. */
|
|
33
|
+
privateAsset: (id, name) => {
|
|
34
|
+
assertSafeKey(id, 'orgId');
|
|
35
|
+
assertSafeKey(name, 'assetName');
|
|
36
|
+
return `orgs/${id}/private/${name}`;
|
|
37
|
+
},
|
|
38
|
+
prefix: (id) => {
|
|
39
|
+
assertSafeKey(id, 'orgId');
|
|
40
|
+
return `orgs/${id}/`;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/organizations/paths.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,SAAS,aAAa,CAAC,KAAa,EAAE,KAAa;IAClD,IAAI,CAAC,KAAK,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnF,MAAM,IAAI,KAAK,CAAC,UAAU,KAAK,KAAK,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC9D,CAAC;AACF,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG;IACvB,KAAK,EAAE,CAAC,EAAU,EAAE,IAAkB,EAAE,EAAE;QACzC,aAAa,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QAC3B,aAAa,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QACjC,OAAO,QAAQ,EAAE,aAAa,IAAI,OAAO,CAAC;IAC3C,CAAC;IACD,qFAAqF;IACrF,YAAY,EAAE,CAAC,EAAU,EAAE,IAAY,EAAE,EAAE;QAC1C,aAAa,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QAC3B,aAAa,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QACjC,OAAO,QAAQ,EAAE,YAAY,IAAI,EAAE,CAAC;IACrC,CAAC;IACD,MAAM,EAAE,CAAC,EAAU,EAAE,EAAE;QACtB,aAAa,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QAC3B,OAAO,QAAQ,EAAE,GAAG,CAAC;IACtB,CAAC;CACQ,CAAC"}
|
|
@@ -7,6 +7,16 @@ export declare const OrgRoleSchema: z.ZodEnum<{
|
|
|
7
7
|
member: "member";
|
|
8
8
|
}>;
|
|
9
9
|
export type OrgRole = z.infer<typeof OrgRoleSchema>;
|
|
10
|
+
/**
|
|
11
|
+
* Kinds of org-scoped branding asset. Adding a new kind is a single entry here
|
|
12
|
+
* — the storage path, upload route, store, and UI are all generic over it.
|
|
13
|
+
*/
|
|
14
|
+
export declare const OrgAssetKindSchema: z.ZodEnum<{
|
|
15
|
+
logo: "logo";
|
|
16
|
+
favicon: "favicon";
|
|
17
|
+
}>;
|
|
18
|
+
export type OrgAssetKind = z.infer<typeof OrgAssetKindSchema>;
|
|
19
|
+
export declare const ALL_ORG_ASSET_KINDS: readonly OrgAssetKind[];
|
|
10
20
|
/** Org-scope permissions. A user may hold different sets in different orgs. */
|
|
11
21
|
export declare const OrgPermissionSchema: z.ZodEnum<{
|
|
12
22
|
manage_org_members: "manage_org_members";
|