@selvajs/platform 0.17.0-beta.3 → 0.18.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/README.md +25 -28
- package/dist/access/rules.d.ts +20 -26
- package/dist/access/rules.d.ts.map +1 -1
- package/dist/access/rules.js +16 -16
- package/dist/access/rules.js.map +1 -1
- package/dist/auth/interface.d.ts +99 -116
- package/dist/auth/interface.d.ts.map +1 -1
- package/dist/auth/types.d.ts +1 -4
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/bindings/interface.d.ts +19 -32
- package/dist/bindings/interface.d.ts.map +1 -1
- package/dist/bindings/interface.js +6 -12
- package/dist/bindings/interface.js.map +1 -1
- package/dist/computeServer/interface.d.ts +34 -41
- package/dist/computeServer/interface.d.ts.map +1 -1
- package/dist/computeServer/secrets.d.ts +16 -20
- package/dist/computeServer/secrets.d.ts.map +1 -1
- package/dist/computeServer/secrets.js +11 -12
- package/dist/computeServer/secrets.js.map +1 -1
- package/dist/computeServer/types.d.ts +15 -17
- package/dist/computeServer/types.d.ts.map +1 -1
- package/dist/computeServer/types.js.map +1 -1
- package/dist/computeServer/utils.d.ts +8 -14
- package/dist/computeServer/utils.d.ts.map +1 -1
- package/dist/computeServer/utils.js +8 -16
- package/dist/computeServer/utils.js.map +1 -1
- package/dist/config.d.ts +16 -39
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -2
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +12 -19
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +6 -10
- package/dist/context.js.map +1 -1
- package/dist/data/interface.d.ts +32 -47
- package/dist/data/interface.d.ts.map +1 -1
- package/dist/data/interface.js +7 -10
- package/dist/data/interface.js.map +1 -1
- package/dist/definitions/interface.d.ts +24 -31
- package/dist/definitions/interface.d.ts.map +1 -1
- package/dist/definitions/schemas.d.ts.map +1 -1
- package/dist/definitions/schemas.js +6 -9
- package/dist/definitions/schemas.js.map +1 -1
- package/dist/definitions/types.d.ts +26 -42
- package/dist/definitions/types.d.ts.map +1 -1
- package/dist/definitions/types.js +0 -1
- package/dist/definitions/types.js.map +1 -1
- package/dist/errors/interface.d.ts +4 -8
- package/dist/errors/interface.d.ts.map +1 -1
- package/dist/errors/interface.js.map +1 -1
- package/dist/errors.d.ts +2 -5
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +2 -5
- package/dist/errors.js.map +1 -1
- package/dist/events/audit.d.ts +13 -26
- package/dist/events/audit.d.ts.map +1 -1
- package/dist/events/interface.d.ts +17 -33
- package/dist/events/interface.d.ts.map +1 -1
- package/dist/events/interface.js +7 -22
- package/dist/events/interface.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/invites/interface.d.ts +3 -9
- package/dist/invites/interface.d.ts.map +1 -1
- package/dist/invites/types.d.ts +13 -10
- package/dist/invites/types.d.ts.map +1 -1
- package/dist/logging/interface.d.ts +19 -33
- package/dist/logging/interface.d.ts.map +1 -1
- package/dist/logging/interface.js +9 -17
- package/dist/logging/interface.js.map +1 -1
- package/dist/metrics/interface.d.ts +16 -31
- package/dist/metrics/interface.d.ts.map +1 -1
- package/dist/metrics/interface.js +1 -5
- package/dist/metrics/interface.js.map +1 -1
- package/dist/organizations/interface.d.ts +14 -23
- package/dist/organizations/interface.d.ts.map +1 -1
- package/dist/organizations/paths.d.ts +9 -12
- package/dist/organizations/paths.d.ts.map +1 -1
- package/dist/organizations/paths.js +12 -16
- package/dist/organizations/paths.js.map +1 -1
- package/dist/organizations/schemas.d.ts +10 -19
- package/dist/organizations/schemas.d.ts.map +1 -1
- package/dist/organizations/schemas.js +10 -19
- package/dist/organizations/schemas.js.map +1 -1
- package/dist/organizations/types.d.ts +3 -4
- package/dist/organizations/types.d.ts.map +1 -1
- package/dist/pagination.d.ts +13 -21
- package/dist/pagination.d.ts.map +1 -1
- package/dist/pagination.js.map +1 -1
- package/dist/permissions/interface.d.ts +12 -21
- package/dist/permissions/interface.d.ts.map +1 -1
- package/dist/permissions/types.d.ts +5 -5
- package/dist/permissions/types.js +5 -5
- package/dist/platformProjects/interface.d.ts +7 -14
- package/dist/platformProjects/interface.d.ts.map +1 -1
- package/dist/platformProjects/types.d.ts +1 -4
- package/dist/platformProjects/types.d.ts.map +1 -1
- package/dist/projects/interface.d.ts +12 -17
- package/dist/projects/interface.d.ts.map +1 -1
- package/dist/shareLinks/interface.d.ts +5 -8
- package/dist/shareLinks/interface.d.ts.map +1 -1
- package/dist/shareLinks/schemas.d.ts.map +1 -1
- package/dist/shareLinks/schemas.js +1 -5
- package/dist/shareLinks/schemas.js.map +1 -1
- package/dist/shareLinks/types.d.ts +5 -6
- package/dist/shareLinks/types.d.ts.map +1 -1
- package/dist/shareLinks/types.js.map +1 -1
- package/dist/solveCache/interface.d.ts +32 -46
- package/dist/solveCache/interface.d.ts.map +1 -1
- package/dist/solveCache/interface.js.map +1 -1
- package/dist/storage/assetClasses.d.ts +16 -24
- package/dist/storage/assetClasses.d.ts.map +1 -1
- package/dist/storage/assetClasses.js +21 -28
- package/dist/storage/assetClasses.js.map +1 -1
- package/dist/storage/cacheBust.d.ts +12 -14
- package/dist/storage/cacheBust.d.ts.map +1 -1
- package/dist/storage/cacheBust.js +12 -14
- package/dist/storage/cacheBust.js.map +1 -1
- package/dist/storage/image.d.ts +9 -13
- package/dist/storage/image.d.ts.map +1 -1
- package/dist/storage/image.js +9 -13
- package/dist/storage/image.js.map +1 -1
- package/dist/userProfile/interface.d.ts +1 -1
- package/dist/userProfile/types.d.ts +1 -5
- package/dist/userProfile/types.d.ts.map +1 -1
- package/dist/userProfile/types.js.map +1 -1
- package/package.json +3 -3
package/dist/context.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import type { PlatformPermission } from './permissions/types.js';
|
|
2
2
|
import type { OrgPermission } from './organizations/schemas.js';
|
|
3
3
|
/**
|
|
4
|
-
* Per-request identity + scope passed to every data provider call
|
|
5
|
-
*
|
|
4
|
+
* Per-request identity + scope passed to every data provider call, built once
|
|
5
|
+
* per HTTP request from the authenticated session.
|
|
6
6
|
*
|
|
7
7
|
* `actingOrgId` is the org the user is currently acting as — NOT "an org the
|
|
8
8
|
* user is a member of." Tenancy checks compare it to the resource's `orgId`.
|
|
9
9
|
*
|
|
10
|
-
* `instance_admin` implies every other permission
|
|
11
|
-
* `
|
|
12
|
-
*
|
|
10
|
+
* `instance_admin` implies every other permission everywhere, via `hasPermission`.
|
|
11
|
+
* `system: true` marks a trusted server-internal call; adapters with RLS treat it
|
|
12
|
+
* as fully authorized.
|
|
13
13
|
*/
|
|
14
14
|
export interface RequestContext {
|
|
15
15
|
/** Empty string for system contexts. */
|
|
@@ -21,28 +21,21 @@ export interface RequestContext {
|
|
|
21
21
|
orgPermissions: OrgPermission[];
|
|
22
22
|
/** Never derive from a user session. */
|
|
23
23
|
system?: true;
|
|
24
|
-
/**
|
|
25
|
-
* Opaque adapter payload. The Supabase adapter passes the user JWT through
|
|
26
|
-
* for RLS; local ignores it.
|
|
27
|
-
*/
|
|
24
|
+
/** Opaque adapter payload — the Supabase adapter passes the user JWT through for RLS; local ignores it. */
|
|
28
25
|
adapterContext?: unknown;
|
|
29
26
|
}
|
|
30
|
-
/**
|
|
31
|
-
* For server-internal operations outside any HTTP request (bootstrap,
|
|
32
|
-
* janitors, migrations). Treated as fully authorized.
|
|
33
|
-
*/
|
|
27
|
+
/** For server-internal operations outside any HTTP request (bootstrap, janitors, migrations). */
|
|
34
28
|
export declare const SYSTEM_CONTEXT: RequestContext;
|
|
35
29
|
/**
|
|
36
|
-
* Does
|
|
37
|
-
* to the org
|
|
30
|
+
* Does not cross-check `ctx.actingOrgId` — the caller must build a context scoped
|
|
31
|
+
* to the org it's acting on. An org permission against a context without
|
|
38
32
|
* `actingOrgId` returns false unless `instance_admin` or `system`.
|
|
39
33
|
*/
|
|
40
34
|
export declare function hasPermission(ctx: RequestContext, permission: PlatformPermission | OrgPermission): boolean;
|
|
41
35
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
* rather than a `null` that leaks into a query as `org_id = undefined`.
|
|
36
|
+
* Returns the org the caller is acting as, or throws `ProviderError(403)`.
|
|
37
|
+
* Centralizes this guard so every store that scopes rows to an acting org fails
|
|
38
|
+
* the same consistent way, instead of leaking `org_id = undefined` into a query.
|
|
46
39
|
*/
|
|
47
40
|
export declare function requireActingOrg(ctx: RequestContext): string;
|
|
48
41
|
//# 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;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
|
|
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,2GAA2G;IAC3G,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,iGAAiG;AACjG,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;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,CAK5D"}
|
package/dist/context.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { ALL_PLATFORM_PERMISSIONS } from './permissions/types.js';
|
|
2
2
|
import { ALL_ORG_PERMISSIONS } from './organizations/schemas.js';
|
|
3
3
|
import { ProviderError } from './errors.js';
|
|
4
|
-
/**
|
|
5
|
-
* For server-internal operations outside any HTTP request (bootstrap,
|
|
6
|
-
* janitors, migrations). Treated as fully authorized.
|
|
7
|
-
*/
|
|
4
|
+
/** For server-internal operations outside any HTTP request (bootstrap, janitors, migrations). */
|
|
8
5
|
export const SYSTEM_CONTEXT = {
|
|
9
6
|
userId: '',
|
|
10
7
|
platformPermissions: [...ALL_PLATFORM_PERMISSIONS],
|
|
@@ -12,8 +9,8 @@ export const SYSTEM_CONTEXT = {
|
|
|
12
9
|
system: true
|
|
13
10
|
};
|
|
14
11
|
/**
|
|
15
|
-
* Does
|
|
16
|
-
* to the org
|
|
12
|
+
* Does not cross-check `ctx.actingOrgId` — the caller must build a context scoped
|
|
13
|
+
* to the org it's acting on. An org permission against a context without
|
|
17
14
|
* `actingOrgId` returns false unless `instance_admin` or `system`.
|
|
18
15
|
*/
|
|
19
16
|
export function hasPermission(ctx, permission) {
|
|
@@ -31,10 +28,9 @@ function isPlatformPermission(p) {
|
|
|
31
28
|
return PLATFORM_PERMISSION_VALUES.has(p);
|
|
32
29
|
}
|
|
33
30
|
/**
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* rather than a `null` that leaks into a query as `org_id = undefined`.
|
|
31
|
+
* Returns the org the caller is acting as, or throws `ProviderError(403)`.
|
|
32
|
+
* Centralizes this guard so every store that scopes rows to an acting org fails
|
|
33
|
+
* the same consistent way, instead of leaking `org_id = undefined` into a query.
|
|
38
34
|
*/
|
|
39
35
|
export function requireActingOrg(ctx) {
|
|
40
36
|
if (!ctx.actingOrgId) {
|
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;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,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;AA2B5C,iGAAiG;AACjG,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;;;;GAIG;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"}
|
package/dist/data/interface.d.ts
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* lives here.
|
|
2
|
+
* Composition root bundling every store an adapter implements. Individual
|
|
3
|
+
* interfaces (`IOrgStore`, `IProjectStore`, …) live next to their types in
|
|
4
|
+
* their own subdirs.
|
|
6
5
|
*
|
|
7
6
|
* Every store method takes a `RequestContext` first. **The query itself is
|
|
8
7
|
* the security boundary** — adapters MUST scope reads/writes by `ctx`. An
|
|
9
8
|
* unauthorized caller sees an empty page, `null`, or a `ProviderError`.
|
|
10
9
|
*
|
|
11
|
-
* Access-control predicates live in `@selvajs/platform/access
|
|
12
|
-
* Stores do storage; rules do rules.
|
|
10
|
+
* Access-control predicates live in `@selvajs/platform/access`, not here.
|
|
13
11
|
*/
|
|
14
12
|
import type { IOrgStore } from '../organizations/interface.js';
|
|
15
13
|
import type { IProjectStore } from '../projects/interface.js';
|
|
@@ -24,10 +22,10 @@ import type { IAuditQuery } from '../events/audit.js';
|
|
|
24
22
|
import type { IEventSink } from '../events/interface.js';
|
|
25
23
|
import type { RequestContext } from '../context.js';
|
|
26
24
|
/**
|
|
27
|
-
* Result of the app↔DB schema handshake
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
25
|
+
* Result of the app↔DB schema handshake. `expected` is the migration head
|
|
26
|
+
* the running app was built against; `actual` is what the database reports
|
|
27
|
+
* (`null` when the database can't even answer — e.g. the handshake function
|
|
28
|
+
* itself was never migrated in).
|
|
31
29
|
*/
|
|
32
30
|
export interface SchemaVersionReport {
|
|
33
31
|
ok: boolean;
|
|
@@ -36,20 +34,15 @@ export interface SchemaVersionReport {
|
|
|
36
34
|
/** Operator-facing explanation + recovery hint when not ok. */
|
|
37
35
|
message?: string;
|
|
38
36
|
}
|
|
39
|
-
/**
|
|
40
|
-
* Extra identifiers for {@link IDataProvider.onUserDeleted} erasure that are
|
|
41
|
-
* not derivable from the userId alone. Captured by the caller BEFORE the auth
|
|
42
|
-
* user is deleted (see the method's contract).
|
|
43
|
-
*/
|
|
37
|
+
/** Extra identifiers {@link IDataProvider.onUserDeleted} needs but can't derive from userId alone. */
|
|
44
38
|
export interface UserErasureOptions {
|
|
45
39
|
/** The deleted user's email, for scrubbing invite/audit rows keyed by it. */
|
|
46
40
|
email?: string;
|
|
47
41
|
}
|
|
48
42
|
/**
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* were never attributed to a user (share-link / server flows).
|
|
43
|
+
* Written to `solve_metrics.actor_id` when a user is erased, so capacity/billing
|
|
44
|
+
* aggregates survive without identifying the person. Distinct from `'system'`,
|
|
45
|
+
* which marks solves never attributed to a user (share-link / server flows).
|
|
53
46
|
*/
|
|
54
47
|
export declare const ERASED_ACTOR_ID = "deleted";
|
|
55
48
|
export interface IDataProvider {
|
|
@@ -69,31 +62,27 @@ export interface IDataProvider {
|
|
|
69
62
|
*/
|
|
70
63
|
auditQuery?: IAuditQuery;
|
|
71
64
|
/**
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
* Callers fall back to `NoopEventSink` when absent.
|
|
65
|
+
* Write-side event sink this provider's stores emit into. Optional — lets app
|
|
66
|
+
* code with no store mutation to piggyback on (e.g. a self-update route) emit
|
|
67
|
+
* domain events into the same log. Callers fall back to `NoopEventSink` when absent.
|
|
76
68
|
*/
|
|
77
69
|
events?: IEventSink;
|
|
78
70
|
/**
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
* drives `/api/health` to 503 when the database is behind the app, so
|
|
84
|
-
* monitoring — and the self-update runner's health probe — catch schema
|
|
85
|
-
* skew instead of surfacing it as per-request store errors.
|
|
71
|
+
* Optional — only adapters whose schema migrates out-of-band (Supabase:
|
|
72
|
+
* `supabase db push` is a manual operator step) need this. Boot health calls
|
|
73
|
+
* it and drives `/api/health` to 503 when the database is behind the app,
|
|
74
|
+
* so schema skew surfaces as a health check instead of per-request store errors.
|
|
86
75
|
*
|
|
87
76
|
* MUST NOT throw: report failure via `ok: false`.
|
|
88
77
|
*/
|
|
89
78
|
verifySchemaVersion?(): Promise<SchemaVersionReport>;
|
|
90
79
|
/**
|
|
91
|
-
* Idempotently
|
|
80
|
+
* Idempotently registers a user in the data layer. Called by `hooks.server.ts`
|
|
92
81
|
* after `verifyToken` succeeds, so the data layer always has a row for the
|
|
93
82
|
* authenticated user regardless of which auth provider issued the ID.
|
|
94
83
|
*
|
|
95
84
|
* Adapters with a DB-side trigger that auto-seeds on auth signup (Supabase)
|
|
96
|
-
* make this a no-op. Adapters
|
|
85
|
+
* make this a no-op. Adapters owning a separate user-data table without a
|
|
97
86
|
* trigger (local-provider) upsert here.
|
|
98
87
|
*
|
|
99
88
|
* MUST be safe to call concurrently and on every request. MUST NOT throw on
|
|
@@ -102,26 +91,22 @@ export interface IDataProvider {
|
|
|
102
91
|
ensureUser(ctx: RequestContext, userId: string): Promise<void>;
|
|
103
92
|
/**
|
|
104
93
|
* Cascade + erasure hook called after the auth provider deletes a user.
|
|
105
|
-
* Removes or anonymizes
|
|
106
|
-
* row, and any personal data keyed by `userId` or `email` that should not
|
|
107
|
-
* outlive the identity).
|
|
94
|
+
* Removes or anonymizes data-layer rows tied to that user.
|
|
108
95
|
*
|
|
109
|
-
* Most user-owned rows die via FK cascade / `set null` against
|
|
110
|
-
*
|
|
111
|
-
*
|
|
96
|
+
* Most user-owned rows die via FK cascade / `set null` against `auth.users`
|
|
97
|
+
* (Supabase) or explicit membership cleanup (local). Some personal data is
|
|
98
|
+
* NOT reachable by those FKs and MUST be scrubbed here:
|
|
112
99
|
* - audit rows keyed by a plain-text `actor_id` (no FK),
|
|
113
|
-
* - invites addressed to the user's `email
|
|
114
|
-
*
|
|
115
|
-
* -
|
|
116
|
-
*
|
|
100
|
+
* - invites addressed to the user's `email`, and that email embedded in
|
|
101
|
+
* `invite.created` audit payloads,
|
|
102
|
+
* - `solve_metrics`, deliberately not FK-cascaded — anonymized (actor
|
|
103
|
+
* tombstoned), not deleted.
|
|
117
104
|
*
|
|
118
|
-
* `opts.email` is the deleted user's email
|
|
105
|
+
* `opts.email` is the deleted user's email; the CALLER must capture it
|
|
119
106
|
* BEFORE `deleteUser` runs (the auth user is already gone by the time this
|
|
120
|
-
* hook fires
|
|
121
|
-
* scrubs are skipped — pass it to fully close erasure.
|
|
107
|
+
* hook fires). When absent, email-keyed scrubs are skipped.
|
|
122
108
|
*
|
|
123
|
-
* MUST tolerate a missing user and missing rows (idempotent — caller may
|
|
124
|
-
* retry).
|
|
109
|
+
* MUST tolerate a missing user and missing rows (idempotent — caller may retry).
|
|
125
110
|
*/
|
|
126
111
|
onUserDeleted(ctx: RequestContext, userId: string, opts?: UserErasureOptions): Promise<void>;
|
|
127
112
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/data/interface.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/data/interface.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,kCAAkC,CAAC;AACnF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IACnC,EAAE,EAAE,OAAO,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,sGAAsG;AACtG,MAAM,WAAW,kBAAkB;IAClC,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,eAAO,MAAM,eAAe,YAAY,CAAC;AAEzC,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,aAAa,CAAC;IACxB,WAAW,EAAE,gBAAgB,CAAC;IAC9B,aAAa,EAAE,mBAAmB,CAAC;IACnC,OAAO,EAAE,YAAY,CAAC;IACtB,UAAU,EAAE,eAAe,CAAC;IAC5B,WAAW,EAAE,iBAAiB,CAAC;IAC/B,WAAW,EAAE,wBAAwB,CAAC;IACtC,qBAAqB,EAAE,0BAA0B,CAAC;IAClD;;;;OAIG;IACH,UAAU,CAAC,EAAE,WAAW,CAAC;IACzB;;;;OAIG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC;IAEpB;;;;;;;OAOG;IACH,mBAAmB,CAAC,IAAI,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAErD;;;;;;;;;;;OAWG;IACH,UAAU,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE/D;;;;;;;;;;;;;;;;;;OAkBG;IACH,aAAa,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7F"}
|
package/dist/data/interface.js
CHANGED
|
@@ -1,21 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* lives here.
|
|
2
|
+
* Composition root bundling every store an adapter implements. Individual
|
|
3
|
+
* interfaces (`IOrgStore`, `IProjectStore`, …) live next to their types in
|
|
4
|
+
* their own subdirs.
|
|
6
5
|
*
|
|
7
6
|
* Every store method takes a `RequestContext` first. **The query itself is
|
|
8
7
|
* the security boundary** — adapters MUST scope reads/writes by `ctx`. An
|
|
9
8
|
* unauthorized caller sees an empty page, `null`, or a `ProviderError`.
|
|
10
9
|
*
|
|
11
|
-
* Access-control predicates live in `@selvajs/platform/access
|
|
12
|
-
* Stores do storage; rules do rules.
|
|
10
|
+
* Access-control predicates live in `@selvajs/platform/access`, not here.
|
|
13
11
|
*/
|
|
14
12
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* were never attributed to a user (share-link / server flows).
|
|
13
|
+
* Written to `solve_metrics.actor_id` when a user is erased, so capacity/billing
|
|
14
|
+
* aggregates survive without identifying the person. Distinct from `'system'`,
|
|
15
|
+
* which marks solves never attributed to a user (share-link / server flows).
|
|
19
16
|
*/
|
|
20
17
|
export const ERASED_ACTOR_ID = 'deleted';
|
|
21
18
|
//# sourceMappingURL=interface.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interface.js","sourceRoot":"","sources":["../../src/data/interface.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"interface.js","sourceRoot":"","sources":["../../src/data/interface.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAmCH;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,SAAS,CAAC"}
|
|
@@ -4,16 +4,15 @@ import type { UISchema } from '@selvajs/schemas';
|
|
|
4
4
|
import type { DefinitionRecord, DefinitionRecordPatch, DefinitionVersion } from './types.js';
|
|
5
5
|
/**
|
|
6
6
|
* Definition metadata + version store. Blob contents live in `IStorageProvider`;
|
|
7
|
-
* this
|
|
8
|
-
*
|
|
7
|
+
* this tracks the parent record, immutable version rows, and the `live`/`draft`
|
|
8
|
+
* channel pointers.
|
|
9
9
|
*/
|
|
10
10
|
export interface IDefinitionStore {
|
|
11
11
|
list(ctx: RequestContext, opts?: DefinitionListOptions): Promise<Page<DefinitionRecord>>;
|
|
12
12
|
listByProject(ctx: RequestContext, projectId: string, opts?: DefinitionListOptions): Promise<Page<DefinitionRecord>>;
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
15
|
-
* Pass `orgId` to restrict to one org; omit for cross-org listing
|
|
16
|
-
* whatever tenant boundary the adapter already enforces.
|
|
14
|
+
* Lists definitions whose parent project has `visibility === 'public'`.
|
|
15
|
+
* Pass `orgId` to restrict to one org; omit for cross-org listing.
|
|
17
16
|
*/
|
|
18
17
|
listPublic(ctx: RequestContext, opts?: DefinitionListOptions & {
|
|
19
18
|
orgId?: string;
|
|
@@ -23,39 +22,35 @@ export interface IDefinitionStore {
|
|
|
23
22
|
update(ctx: RequestContext, guid: string, patch: DefinitionRecordPatch): Promise<void>;
|
|
24
23
|
delete(ctx: RequestContext, guid: string): Promise<void>;
|
|
25
24
|
/**
|
|
26
|
-
* Cascade hook: soft-
|
|
27
|
-
* `IProjectStore.deleteProject` —
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* `deleteByProject` cascade hooks on `IPlatformProjectGrantStore`.
|
|
25
|
+
* Cascade hook: soft-deletes every live definition in a project. Called by
|
|
26
|
+
* `IProjectStore.deleteProject` — definitions surface in library/public
|
|
27
|
+
* listings independent of the project row, so a deleted project must not
|
|
28
|
+
* keep serving them. No-op when the project has none.
|
|
31
29
|
*/
|
|
32
30
|
deleteByProject(ctx: RequestContext, projectId: string): Promise<void>;
|
|
33
31
|
/** Atomic +1 on the solve counter. No-op if the record doesn't exist. */
|
|
34
32
|
incrementSolveCount(ctx: RequestContext, guid: string): Promise<void>;
|
|
35
33
|
/**
|
|
36
|
-
* Atomically
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* fresh `fileKey` instead of overwriting the deleted blob's key. Throws if the
|
|
42
|
-
* definition doesn't exist.
|
|
34
|
+
* Atomically returns the current `nextVersionNumber` and advances the counter
|
|
35
|
+
* by 1, so concurrent uploads never collide on a number/fileKey. Never
|
|
36
|
+
* decremented — deleting the latest version doesn't free its number, so a
|
|
37
|
+
* delete-then-reupload mints a fresh `fileKey` instead of reusing the deleted
|
|
38
|
+
* blob's key. Throws if the definition doesn't exist.
|
|
43
39
|
*/
|
|
44
40
|
reserveNextVersionNumber(ctx: RequestContext, guid: string): Promise<number>;
|
|
45
41
|
createVersion(ctx: RequestContext, version: DefinitionVersion): Promise<void>;
|
|
46
42
|
/**
|
|
47
|
-
* Newest first by `versionNumber`.
|
|
48
|
-
*
|
|
49
|
-
*
|
|
43
|
+
* Newest first by `versionNumber`. `schema` is always `undefined` on listed
|
|
44
|
+
* rows regardless of what's stored — it's a large blob no list caller needs.
|
|
45
|
+
* Use `getVersion` for the schema.
|
|
50
46
|
*/
|
|
51
47
|
listVersions(ctx: RequestContext, definitionId: string, opts?: ListOptions): Promise<Page<DefinitionVersion>>;
|
|
52
48
|
/** The full row, including the cached `schema` when one has been extracted. */
|
|
53
49
|
getVersion(ctx: RequestContext, versionId: string): Promise<DefinitionVersion | null>;
|
|
54
50
|
/**
|
|
55
|
-
*
|
|
56
|
-
* upload path
|
|
57
|
-
*
|
|
58
|
-
* the version doesn't exist.
|
|
51
|
+
* Sets the cached compute-extracted schema on a version row. Used by the
|
|
52
|
+
* upload path and the solve-time backfill bridge for pre-existing versions.
|
|
53
|
+
* No-op if the version doesn't exist.
|
|
59
54
|
*/
|
|
60
55
|
setVersionSchema(ctx: RequestContext, versionId: string, schema: UISchema): Promise<void>;
|
|
61
56
|
/**
|
|
@@ -69,16 +64,14 @@ export interface IDefinitionStore {
|
|
|
69
64
|
/**
|
|
70
65
|
* Atomic `'pending'` → `'draft'` bootstrap. Sets BOTH `liveVersionId` and
|
|
71
66
|
* `draftVersionId` to `versionId` and flips `status` to `'draft'` in a
|
|
72
|
-
* single update
|
|
73
|
-
*
|
|
74
|
-
*
|
|
67
|
+
* single update, so a mid-flight failure can't leave the record
|
|
68
|
+
* half-promoted (draft status with a null channel pointer, or pending
|
|
69
|
+
* status with channels set).
|
|
75
70
|
*
|
|
76
71
|
* Validates that `versionId` belongs to `definitionId` (404 if not).
|
|
77
72
|
*
|
|
78
|
-
* Does NOT emit `definition.published
|
|
79
|
-
*
|
|
80
|
-
* `definition.published` is reserved for explicit publish ops via
|
|
81
|
-
* `setLiveVersion`.
|
|
73
|
+
* Does NOT emit `definition.published` — that event is reserved for
|
|
74
|
+
* explicit publish via `setLiveVersion`.
|
|
82
75
|
*/
|
|
83
76
|
attachInitialVersion(ctx: RequestContext, definitionId: string, versionId: string): Promise<void>;
|
|
84
77
|
}
|
|
@@ -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
|
|
1
|
+
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/definitions/interface.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/definitions/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,UAAU,QAAoE,CAAC;AAE5F,eAAO,MAAM,UAAU,aAAsD,CAAC;
|
|
1
|
+
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/definitions/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,UAAU,QAAoE,CAAC;AAE5F,eAAO,MAAM,UAAU,aAAsD,CAAC;AAK9E,eAAO,MAAM,sBAAsB;;;;EAA6C,CAAC;AAEjF,eAAO,MAAM,uBAAuB;;;EAAwB,CAAC;AAE7D,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;iBAalC,CAAC;AAEH,eAAO,MAAM,uBAAuB;;;EAA4B,CAAC;AAEjE,oDAAoD;AACpD,eAAO,MAAM,2BAA2B;;;;;;;;iBAQtC,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;iBAYpC,CAAC;AAEH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE5E,uDAAuD;AACvD,eAAO,MAAM,yBAAyB;;kBAIzB,CAAC"}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
export const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
3
3
|
export const GuidSchema = z.string().regex(UUID_REGEX, 'Invalid GUID format');
|
|
4
|
-
// Intentionally omits `pending`
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// update, so it is absent from this input validator by design, not by drift. (`review`
|
|
8
|
-
// was a dead fifth value dropped from the DB CHECK in migration 20260716120000 — audit D2.)
|
|
4
|
+
// Intentionally omits `pending` (see `DefinitionStatus` in ./types.ts): it's a
|
|
5
|
+
// create-internal state `DefinitionService.create` writes during the
|
|
6
|
+
// metadata-first window, and a client must never hand-set it through an update.
|
|
9
7
|
export const DefinitionStatusSchema = z.enum(['draft', 'published', 'archived']);
|
|
10
8
|
export const DefinitionFileExtSchema = z.enum(['gh', 'ghx']);
|
|
11
9
|
export const DefinitionVersionSchema = z.object({
|
|
@@ -18,8 +16,7 @@ export const DefinitionVersionSchema = z.object({
|
|
|
18
16
|
uploadedBy: z.string().min(1),
|
|
19
17
|
uploadedAt: z.string(),
|
|
20
18
|
changeNote: z.string().max(1000).optional(),
|
|
21
|
-
//
|
|
22
|
-
// Rhino.Compute at upload, not here — this only asserts it's an object.
|
|
19
|
+
// Rhino.Compute validates structural correctness at upload; this only asserts it's an object.
|
|
23
20
|
schema: z.record(z.string(), z.unknown()).optional(),
|
|
24
21
|
schemaExtractedAt: z.string().optional()
|
|
25
22
|
});
|
|
@@ -48,8 +45,8 @@ export const UpdateMetadataInputSchema = z.object({
|
|
|
48
45
|
tags: z.array(z.string().max(64)).max(20).nullable().optional(),
|
|
49
46
|
projectId: GuidSchema.optional(),
|
|
50
47
|
computeServerId: GuidSchema.nullable().optional(),
|
|
51
|
-
//
|
|
52
|
-
//
|
|
48
|
+
// 0 = off, N = per-definition entry cap, null = inherit the global default.
|
|
49
|
+
// Bounded so a settings typo can't request a runaway quota.
|
|
53
50
|
solveCacheLimit: z.number().int().min(0).max(100_000).nullable().optional(),
|
|
54
51
|
status: DefinitionStatusSchema.optional()
|
|
55
52
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../src/definitions/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,UAAU,GAAG,iEAAiE,CAAC;AAE5F,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,qBAAqB,CAAC,CAAC;AAE9E
|
|
1
|
+
{"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../src/definitions/schemas.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,27 +8,21 @@ export declare const COVER_IMAGE_CONTENT_TYPES: Record<string, string>;
|
|
|
8
8
|
* - `pending` — internal: metadata written, blob upload may be in flight.
|
|
9
9
|
* - `draft` — work in progress, not visible to runners.
|
|
10
10
|
* - `published` — live, visible to all with solve access.
|
|
11
|
-
* - `archived` — retired but preserved
|
|
12
|
-
* intact; restore via `update({ status: 'draft' | 'published' })`.
|
|
11
|
+
* - `archived` — retired but preserved; restore via `update({ status: 'draft' | 'published' })`.
|
|
13
12
|
*
|
|
14
|
-
* List endpoints filter `pending` and `archived` by default (opt in via
|
|
15
|
-
* `DefinitionListOptions.includePending
|
|
16
|
-
* explicit `statuses` filter).
|
|
13
|
+
* List endpoints filter out `pending` and `archived` by default (opt in via
|
|
14
|
+
* `DefinitionListOptions.includePending`/`includeArchived`, or an explicit `statuses` filter).
|
|
17
15
|
*/
|
|
18
16
|
export type DefinitionStatus = 'pending' | 'draft' | 'published' | 'archived';
|
|
19
17
|
/**
|
|
20
18
|
* Immutable snapshot of a definition's `.gh` file at a point in time. New
|
|
21
19
|
* uploads create new versions; rollback re-points the parent's
|
|
22
|
-
* `liveVersionId`
|
|
20
|
+
* `liveVersionId` rather than mutating the version itself.
|
|
23
21
|
*/
|
|
24
22
|
export interface DefinitionVersion {
|
|
25
23
|
id: string;
|
|
26
24
|
definitionId: string;
|
|
27
|
-
/**
|
|
28
|
-
* Monotonic integer starting at 1; NEVER reused — allocated from the parent
|
|
29
|
-
* record's `nextVersionNumber` counter, which only ever advances. Deleting the
|
|
30
|
-
* latest version does not free its number, so `fileKey`s never collide.
|
|
31
|
-
*/
|
|
25
|
+
/** Allocated from `DefinitionRecord.nextVersionNumber`; see that field for the numbering guarantee. */
|
|
32
26
|
versionNumber: number;
|
|
33
27
|
fileExt: DefinitionFileExt;
|
|
34
28
|
/** Full storage key. Opaque to callers. */
|
|
@@ -40,9 +34,8 @@ export interface DefinitionVersion {
|
|
|
40
34
|
changeNote?: string;
|
|
41
35
|
/**
|
|
42
36
|
* Compute-extracted UI schema, cached at upload so the render path doesn't
|
|
43
|
-
* re-fetch it from Rhino.Compute on every load. Optional only
|
|
44
|
-
* lazy-backfill bridge
|
|
45
|
-
* selva/specs/SchemaCaching.md); new uploads always set it.
|
|
37
|
+
* re-fetch it from Rhino.Compute on every load. Optional only for the
|
|
38
|
+
* lazy-backfill bridge on pre-existing versions; new uploads always set it.
|
|
46
39
|
*/
|
|
47
40
|
schema?: UISchema;
|
|
48
41
|
/** ISO timestamp of when `schema` was extracted. */
|
|
@@ -58,15 +51,12 @@ export interface DefinitionRecord {
|
|
|
58
51
|
/** Falls back to the org default, then the platform default. */
|
|
59
52
|
computeServerId?: string;
|
|
60
53
|
/**
|
|
61
|
-
* Per-definition quota for a shared solve-result cache: `0` = caching off
|
|
62
|
-
*
|
|
63
|
-
* solves, absent = inherit whatever default the backend defines.
|
|
54
|
+
* Per-definition quota for a shared solve-result cache: `0` = caching off,
|
|
55
|
+
* `N` = keep at most N cached solves, absent = inherit the backend default.
|
|
64
56
|
*
|
|
65
|
-
* **Dormant.** No shared backend ships today (see `ISolveResultCache`), so
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* knob the moment a backend is wired — so it stays rather than becoming a data
|
|
69
|
-
* migration to remove and re-add.
|
|
57
|
+
* **Dormant.** No shared backend ships today (see `ISolveResultCache`), so
|
|
58
|
+
* this affects nothing at solve time yet. Kept as a persisted column rather
|
|
59
|
+
* than removed, since it's the right knob once a backend exists.
|
|
70
60
|
*/
|
|
71
61
|
solveCacheLimit?: number;
|
|
72
62
|
displayName: string;
|
|
@@ -78,13 +68,11 @@ export interface DefinitionRecord {
|
|
|
78
68
|
status: DefinitionStatus;
|
|
79
69
|
solveCount: number;
|
|
80
70
|
/**
|
|
81
|
-
* Monotonic version-number allocator
|
|
82
|
-
* value
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
* the key) serve the old version's bytes for the new content. Starts at 2
|
|
87
|
-
* after v1 is created.
|
|
71
|
+
* Monotonic version-number allocator, never decremented: the next upload
|
|
72
|
+
* reserves this value then advances the counter, so a delete-latest-then-reupload
|
|
73
|
+
* mints a fresh number and `fileKey` instead of reusing one — otherwise a stale
|
|
74
|
+
* storage blob could serve the old version's bytes under the new content's key.
|
|
75
|
+
* Starts at 2 after v1 is created.
|
|
88
76
|
*/
|
|
89
77
|
nextVersionNumber: number;
|
|
90
78
|
/**
|
|
@@ -95,19 +83,18 @@ export interface DefinitionRecord {
|
|
|
95
83
|
draftVersionId: string | null;
|
|
96
84
|
createdAt: string;
|
|
97
85
|
updatedAt: string;
|
|
86
|
+
/** Soft-delete marker, independent of `status`: a store filters this out regardless of `archived`. */
|
|
98
87
|
deletedAt?: string | null;
|
|
99
88
|
}
|
|
100
89
|
/**
|
|
101
|
-
*
|
|
102
|
-
* `GET /api/v1/definitions` returns.
|
|
90
|
+
* List-row projection of a `DefinitionRecord`; the shape `GET /api/v1/definitions` returns.
|
|
103
91
|
*
|
|
104
|
-
* Deliberately narrower than the full record
|
|
105
|
-
* `updatedBy`,
|
|
106
|
-
*
|
|
107
|
-
* narrowing is free now and impossible later.
|
|
92
|
+
* Deliberately narrower than the full record — `ownerId`, `createdBy`,
|
|
93
|
+
* `updatedBy`, `solveCacheLimit` are internal. v1 is additive-only, so a field
|
|
94
|
+
* published here can only be removed in v2: narrowing later is not an option.
|
|
108
95
|
*
|
|
109
|
-
* `liveVersionId` is the pointer, not a version number
|
|
110
|
-
* native column
|
|
96
|
+
* `liveVersionId` is the pointer, not a version number — the number isn't a
|
|
97
|
+
* native column, so resolving it would cost a query per row.
|
|
111
98
|
*/
|
|
112
99
|
export interface DefinitionListItem {
|
|
113
100
|
guid: string;
|
|
@@ -122,11 +109,10 @@ export interface DefinitionListItem {
|
|
|
122
109
|
liveVersionId: string | null;
|
|
123
110
|
updatedAt: string;
|
|
124
111
|
}
|
|
125
|
-
/** Project a full record down to the fields v1 publishes. */
|
|
126
112
|
export declare function toDefinitionListItem(r: DefinitionRecord): DefinitionListItem;
|
|
127
113
|
/**
|
|
128
|
-
*
|
|
129
|
-
* `setLiveVersion`/`setDraftVersion` for
|
|
114
|
+
* Omits immutable fields and provider-managed ones (use
|
|
115
|
+
* `setLiveVersion`/`setDraftVersion` for channel pointers).
|
|
130
116
|
*
|
|
131
117
|
* - `undefined` — leave unchanged
|
|
132
118
|
* - `null` — clear (only on nullable fields)
|
|
@@ -145,9 +131,7 @@ export interface DefinitionRecordPatch {
|
|
|
145
131
|
/** L2 cache quota (see {@link DefinitionRecord.solveCacheLimit}); `null` clears to inherit. */
|
|
146
132
|
solveCacheLimit?: number | null;
|
|
147
133
|
status?: DefinitionStatus;
|
|
148
|
-
/** Ownership transfer. */
|
|
149
134
|
ownerId?: string;
|
|
150
135
|
}
|
|
151
|
-
/** Channel for solve dispatch. */
|
|
152
136
|
export type DefinitionChannel = 'live' | 'draft';
|
|
153
137
|
//# sourceMappingURL=types.d.ts.map
|