@xemahq/biome-database-nest 0.10.1 → 0.12.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 +38 -23
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/adapter.d.ts.map +1 -1
- package/dist/lib/adapter.js.map +1 -1
- package/dist/lib/control-plane-discovery.d.ts +1 -1
- package/dist/lib/control-plane-discovery.d.ts.map +1 -1
- package/dist/lib/control-plane-discovery.js.map +1 -1
- package/dist/lib/nest/org-erasure.module.d.ts.map +1 -1
- package/dist/lib/nest/org-erasure.module.js +11 -3
- package/dist/lib/nest/org-erasure.module.js.map +1 -1
- package/dist/lib/nest/prisma-service-factory.d.ts +1 -1
- package/dist/lib/nest/prisma-service-factory.d.ts.map +1 -1
- package/dist/lib/nest/prisma-service-factory.js.map +1 -1
- package/dist/lib/schema-name.js.map +1 -1
- package/dist/lib/tenant-isolation/org-erasure.d.ts +7 -0
- package/dist/lib/tenant-isolation/org-erasure.d.ts.map +1 -1
- package/dist/lib/tenant-isolation/org-erasure.js +34 -2
- package/dist/lib/tenant-isolation/org-erasure.js.map +1 -1
- package/dist/lib/tenant-isolation/unscoped-models.d.ts.map +1 -1
- package/dist/lib/tenant-isolation/unscoped-models.js.map +1 -1
- package/package.json +7 -5
- package/src/index.ts +2 -0
- package/src/lib/adapter.ts +6 -3
- package/src/lib/control-plane-discovery.ts +10 -2
- package/src/lib/nest/org-erasure.module.ts +38 -4
- package/src/lib/nest/prisma-service-factory.ts +4 -3
- package/src/lib/schema-name.ts +1 -1
- package/src/lib/tenant-isolation/org-erasure.ts +82 -5
- package/src/lib/tenant-isolation/unscoped-models.ts +4 -1
package/README.md
CHANGED
|
@@ -28,19 +28,33 @@
|
|
|
28
28
|
|
|
29
29
|
## Overview
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
31
|
+
Gives a Xema biome service its database without the service knowing anything
|
|
32
|
+
about databases. It resolves the connection from `org-database-pool-api` at
|
|
33
|
+
boot, builds a schema-qualified Prisma client for it, and applies the service's
|
|
34
|
+
own Prisma migrations before the app serves traffic.
|
|
35
|
+
|
|
36
|
+
A biome carries **no** database configuration: no host, no credential, no URL,
|
|
37
|
+
no schema name, nothing to put in a Helm chart or a secret. Those are facts the
|
|
38
|
+
platform owns, and a biome that had to know them would be a biome that breaks
|
|
39
|
+
when they change.
|
|
40
|
+
|
|
41
|
+
## What a biome gets
|
|
42
|
+
|
|
43
|
+
- **A database of its own, on first boot.** The pool binds the service to it and
|
|
44
|
+
holds it there, so the name can never silently move to an empty schema.
|
|
45
|
+
- **A schema-qualified Prisma client**, already pointed at that database.
|
|
46
|
+
- **Migrations applied at boot** — `prisma migrate deploy`, which THROWS on
|
|
47
|
+
failure, so a bad migration stops the pod becoming ready instead of half-
|
|
48
|
+
applying under live traffic.
|
|
49
|
+
- **More than one database when it needs one.** A biome that ships several API
|
|
50
|
+
services gives each its own; a single service that needs a second declares a
|
|
51
|
+
`dbKey`. Physically these are schemas in the shared `xema_biomes` database —
|
|
52
|
+
`biome_<biomeId>` for the primary, `biome_<biomeId>__<dbKey>` for the rest.
|
|
39
53
|
|
|
40
54
|
## When to use it
|
|
41
55
|
|
|
42
|
-
|
|
43
|
-
|
|
56
|
+
Use it in any NestJS biome service that stores data. There is no second way to
|
|
57
|
+
reach a biome database, and nothing for the service to configure.
|
|
44
58
|
|
|
45
59
|
## Installation
|
|
46
60
|
|
|
@@ -50,6 +64,8 @@ pnpm add @xemahq/biome-database-nest
|
|
|
50
64
|
|
|
51
65
|
## Usage
|
|
52
66
|
|
|
67
|
+
The whole integration:
|
|
68
|
+
|
|
53
69
|
```ts
|
|
54
70
|
import {
|
|
55
71
|
BiomeDatabaseMigrationMode,
|
|
@@ -58,26 +74,25 @@ import {
|
|
|
58
74
|
|
|
59
75
|
BiomeDatabaseModule.forRoot({
|
|
60
76
|
biomeId: 'example',
|
|
61
|
-
migrationMode: BiomeDatabaseMigrationMode.
|
|
62
|
-
databases: [
|
|
77
|
+
migrationMode: BiomeDatabaseMigrationMode.ApplicationManaged,
|
|
78
|
+
databases: [{ workspaceDir: process.cwd() }],
|
|
63
79
|
});
|
|
64
80
|
```
|
|
65
81
|
|
|
66
|
-
|
|
82
|
+
`biomeId` names the database this service owns; it is pinned by the pool on
|
|
83
|
+
first resolve, so changing it later is refused rather than silently pointing the
|
|
84
|
+
service at a fresh empty schema. `workspaceDir` is where the Prisma schema and
|
|
85
|
+
`migrations/` live.
|
|
86
|
+
|
|
87
|
+
A second database for the same service:
|
|
67
88
|
|
|
68
89
|
```ts
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
workspaceDir: process.cwd(),
|
|
72
|
-
|
|
73
|
-
}
|
|
90
|
+
databases: [
|
|
91
|
+
{ workspaceDir: process.cwd() },
|
|
92
|
+
{ key: 'analytics', workspaceDir: `${process.cwd()}/analytics` },
|
|
93
|
+
],
|
|
74
94
|
```
|
|
75
95
|
|
|
76
|
-
Runtime declarations use closed privilege enums. Views, materialized views,
|
|
77
|
-
and foreign tables are SELECT-only unless a writable view or foreign table is
|
|
78
|
-
explicitly named. Runtime-callable functions are exact-overload allowlists;
|
|
79
|
-
`SECURITY DEFINER` functions are never accepted.
|
|
80
|
-
|
|
81
96
|
## Peer requirements
|
|
82
97
|
|
|
83
98
|
- NestJS 10 or 11 and Prisma 7.
|
package/dist/index.d.ts
CHANGED
|
@@ -14,6 +14,6 @@ export { TenantIsolationError, TenantIsolationViolationKind, formatTenantIsolati
|
|
|
14
14
|
export { PrismaModelOperation, scopeArgsToOrg, type OrgScopeOutcome, type OrgScopeRequest, } from './lib/tenant-isolation/org-scope';
|
|
15
15
|
export { DEFAULT_ORG_FIELD, collectOrgScopedModels, createTenantIsolationExtension, readRuntimeModels, type CreateTenantIsolationExtensionOptions, type RuntimeDataModelField, type RuntimeDataModelModel, type TenantIsolationExtensionDefinition, type TenantIsolationLogger, type TenantIsolationQueryContext, } from './lib/tenant-isolation/tenant-isolation.extension';
|
|
16
16
|
export { assertUnscopedModelsDeclared, collectUnscopableModels, formatUnscopedModelReport, normalizeUnscopedModelDeclarations, UndeclaredUnscopedModelsError, type AssertUnscopedModelsOptions, type NormalizedUnscopedModelDeclaration, type UnscopedModelDeclaration, type UnscopedModelDeclarations, } from './lib/tenant-isolation/unscoped-models';
|
|
17
|
-
export { eraseOrgData, OrgErasureBlockedError, type EraseOrgDataOptions, type OrgErasureReport, } from './lib/tenant-isolation/org-erasure';
|
|
17
|
+
export { assertOrgErasureMatchesModels, eraseOrgData, OrgErasureBlockedError, OrgErasureMatchesNothingError, type EraseOrgDataOptions, type OrgErasureReport, } from './lib/tenant-isolation/org-erasure';
|
|
18
18
|
export { OrgErasureModule, OrgErasureController, ORG_ERASURE_RUNNER, ORG_DATA_ERASURE_CAPABILITY, ORG_ERASURE_ROUTE_PATH, type OrgErasureModuleOptions, type OrgErasureRunner, } from './lib/nest/org-erasure.module';
|
|
19
19
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAChF,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,sBAAsB,EACtB,8BAA8B,EAC9B,uBAAuB,EACvB,yBAAyB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,GACxB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,cAAc,EACd,cAAc,EACd,cAAc,EACd,cAAc,EACd,2BAA2B,EAC3B,yBAAyB,EACzB,KAAK,eAAe,GACrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,iCAAiC,EACjC,KAAK,mBAAmB,GACzB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,wBAAwB,EACxB,+BAA+B,GAChC,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,yBAAyB,EACzB,KAAK,2BAA2B,GACjC,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,0BAA0B,EAC1B,8BAA8B,EAC9B,KAAK,4BAA4B,GAClC,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,uBAAuB,EACvB,KAAK,wBAAwB,EAC7B,KAAK,8BAA8B,GACpC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,KAAK,4CAA4C,EACjD,KAAK,0BAA0B,GAChC,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,wBAAwB,EACxB,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,0BAA0B,EAC/B,KAAK,+BAA+B,EACpC,KAAK,6BAA6B,EAClC,KAAK,eAAe,GACrB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,mBAAmB,EACnB,6BAA6B,EAC7B,0BAA0B,GAC3B,MAAM,8CAA8C,CAAC;AACtD,OAAO,EACL,oBAAoB,EACpB,4BAA4B,EAC5B,8BAA8B,EAC9B,KAAK,wBAAwB,GAC9B,MAAM,+CAA+C,CAAC;AACvD,OAAO,EACL,oBAAoB,EACpB,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,eAAe,GACrB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACtB,8BAA8B,EAC9B,iBAAiB,EACjB,KAAK,qCAAqC,EAC1C,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,kCAAkC,EACvC,KAAK,qBAAqB,EAC1B,KAAK,2BAA2B,GACjC,MAAM,mDAAmD,CAAC;AAC3D,OAAO,EACL,4BAA4B,EAC5B,uBAAuB,EACvB,yBAAyB,EACzB,kCAAkC,EAClC,6BAA6B,EAC7B,KAAK,2BAA2B,EAChC,KAAK,kCAAkC,EACvC,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,GAC/B,MAAM,wCAAwC,CAAC;AAChD,OAAO,EACL,YAAY,EACZ,sBAAsB,EACtB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,GACtB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,kBAAkB,EAClB,2BAA2B,EAC3B,sBAAsB,EACtB,KAAK,uBAAuB,EAC5B,KAAK,gBAAgB,GACtB,MAAM,+BAA+B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAChF,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,sBAAsB,EACtB,8BAA8B,EAC9B,uBAAuB,EACvB,yBAAyB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,GACxB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,cAAc,EACd,cAAc,EACd,cAAc,EACd,cAAc,EACd,2BAA2B,EAC3B,yBAAyB,EACzB,KAAK,eAAe,GACrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,iCAAiC,EACjC,KAAK,mBAAmB,GACzB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,wBAAwB,EACxB,+BAA+B,GAChC,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,yBAAyB,EACzB,KAAK,2BAA2B,GACjC,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,0BAA0B,EAC1B,8BAA8B,EAC9B,KAAK,4BAA4B,GAClC,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,uBAAuB,EACvB,KAAK,wBAAwB,EAC7B,KAAK,8BAA8B,GACpC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,KAAK,4CAA4C,EACjD,KAAK,0BAA0B,GAChC,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,wBAAwB,EACxB,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,0BAA0B,EAC/B,KAAK,+BAA+B,EACpC,KAAK,6BAA6B,EAClC,KAAK,eAAe,GACrB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,mBAAmB,EACnB,6BAA6B,EAC7B,0BAA0B,GAC3B,MAAM,8CAA8C,CAAC;AACtD,OAAO,EACL,oBAAoB,EACpB,4BAA4B,EAC5B,8BAA8B,EAC9B,KAAK,wBAAwB,GAC9B,MAAM,+CAA+C,CAAC;AACvD,OAAO,EACL,oBAAoB,EACpB,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,eAAe,GACrB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACtB,8BAA8B,EAC9B,iBAAiB,EACjB,KAAK,qCAAqC,EAC1C,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,kCAAkC,EACvC,KAAK,qBAAqB,EAC1B,KAAK,2BAA2B,GACjC,MAAM,mDAAmD,CAAC;AAC3D,OAAO,EACL,4BAA4B,EAC5B,uBAAuB,EACvB,yBAAyB,EACzB,kCAAkC,EAClC,6BAA6B,EAC7B,KAAK,2BAA2B,EAChC,KAAK,kCAAkC,EACvC,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,GAC/B,MAAM,wCAAwC,CAAC;AAChD,OAAO,EACL,6BAA6B,EAC7B,YAAY,EACZ,sBAAsB,EACtB,6BAA6B,EAC7B,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,GACtB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,kBAAkB,EAClB,2BAA2B,EAC3B,sBAAsB,EACtB,KAAK,uBAAuB,EAC5B,KAAK,gBAAgB,GACtB,MAAM,+BAA+B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.ORG_DATA_ERASURE_CAPABILITY = exports.ORG_ERASURE_RUNNER = exports.OrgErasureController = exports.OrgErasureModule = exports.OrgErasureMatchesNothingError = exports.OrgErasureBlockedError = exports.eraseOrgData = exports.assertOrgErasureMatchesModels = exports.UndeclaredUnscopedModelsError = exports.normalizeUnscopedModelDeclarations = exports.formatUnscopedModelReport = exports.collectUnscopableModels = exports.assertUnscopedModelsDeclared = exports.readRuntimeModels = exports.createTenantIsolationExtension = exports.collectOrgScopedModels = exports.DEFAULT_ORG_FIELD = exports.scopeArgsToOrg = exports.PrismaModelOperation = exports.formatTenantIsolationViolation = exports.TenantIsolationViolationKind = exports.TenantIsolationError = exports.resolveTenantIsolationMode = exports.TENANT_ISOLATION_MODE_ENV_VAR = exports.TenantIsolationMode = exports.createBiomePrismaService = exports.BIOME_DATABASE_READY = exports.BiomeDatabaseModule = exports.BiomeDatabaseMigrationMode = exports.bootstrapBiomeDatabases = exports.ORG_DATABASE_POOL_SERVICE_NAME = exports.resolveControlPlaneBaseUrl = exports.fetchSystemDatabaseConfig = exports.createBiomePrismaAdapterFromEnv = exports.createBiomePrismaAdapter = exports.resolveBiomeDatabaseConfigFromEnv = exports.SCHEMA_ROLE_SUFFIX_LENGTH = exports.SCHEMA_ROLE_BASE_MAX_LENGTH = exports.SchemaRoleKind = exports.schemaRoleName = exports.schemaRoleBase = exports.rolesForSchema = exports.sanitizeIdentifierSegment = exports.sanitizeIdentifierChars = exports.POSTGRES_MAX_IDENTIFIER_LENGTH = exports.IDENTIFIER_HASH_LENGTH = exports.fitIdentifier = exports.composeIdentifier = exports.deriveBiomeSchemaName = exports.DEFAULT_BIOME_DB_KEY = void 0;
|
|
4
|
+
exports.ORG_ERASURE_ROUTE_PATH = void 0;
|
|
4
5
|
var schema_name_1 = require("./lib/schema-name");
|
|
5
6
|
Object.defineProperty(exports, "DEFAULT_BIOME_DB_KEY", { enumerable: true, get: function () { return schema_name_1.DEFAULT_BIOME_DB_KEY; } });
|
|
6
7
|
Object.defineProperty(exports, "deriveBiomeSchemaName", { enumerable: true, get: function () { return schema_name_1.deriveBiomeSchemaName; } });
|
|
@@ -60,8 +61,10 @@ Object.defineProperty(exports, "formatUnscopedModelReport", { enumerable: true,
|
|
|
60
61
|
Object.defineProperty(exports, "normalizeUnscopedModelDeclarations", { enumerable: true, get: function () { return unscoped_models_1.normalizeUnscopedModelDeclarations; } });
|
|
61
62
|
Object.defineProperty(exports, "UndeclaredUnscopedModelsError", { enumerable: true, get: function () { return unscoped_models_1.UndeclaredUnscopedModelsError; } });
|
|
62
63
|
var org_erasure_1 = require("./lib/tenant-isolation/org-erasure");
|
|
64
|
+
Object.defineProperty(exports, "assertOrgErasureMatchesModels", { enumerable: true, get: function () { return org_erasure_1.assertOrgErasureMatchesModels; } });
|
|
63
65
|
Object.defineProperty(exports, "eraseOrgData", { enumerable: true, get: function () { return org_erasure_1.eraseOrgData; } });
|
|
64
66
|
Object.defineProperty(exports, "OrgErasureBlockedError", { enumerable: true, get: function () { return org_erasure_1.OrgErasureBlockedError; } });
|
|
67
|
+
Object.defineProperty(exports, "OrgErasureMatchesNothingError", { enumerable: true, get: function () { return org_erasure_1.OrgErasureMatchesNothingError; } });
|
|
65
68
|
var org_erasure_module_1 = require("./lib/nest/org-erasure.module");
|
|
66
69
|
Object.defineProperty(exports, "OrgErasureModule", { enumerable: true, get: function () { return org_erasure_module_1.OrgErasureModule; } });
|
|
67
70
|
Object.defineProperty(exports, "OrgErasureController", { enumerable: true, get: function () { return org_erasure_module_1.OrgErasureController; } });
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;AAAA,iDAAgF;AAAvE,mHAAA,oBAAoB,OAAA;AAAE,oHAAA,qBAAqB,OAAA;AACpD,+CAS0B;AARxB,+GAAA,iBAAiB,OAAA;AACjB,2GAAA,aAAa,OAAA;AACb,oHAAA,sBAAsB,OAAA;AACtB,4HAAA,8BAA8B,OAAA;AAC9B,qHAAA,uBAAuB,OAAA;AACvB,uHAAA,yBAAyB,OAAA;AAI3B,+CAQ0B;AAPxB,4GAAA,cAAc,OAAA;AACd,4GAAA,cAAc,OAAA;AACd,4GAAA,cAAc,OAAA;AACd,4GAAA,cAAc,OAAA;AACd,yHAAA,2BAA2B,OAAA;AAC3B,uHAAA,yBAAyB,OAAA;AAG3B,uCAGsB;AAFpB,2HAAA,iCAAiC,OAAA;AAGnC,yCAGuB;AAFrB,mHAAA,wBAAwB,OAAA;AACxB,0HAAA,+BAA+B,OAAA;AAEjC,mEAGoC;AAFlC,iIAAA,yBAAyB,OAAA;AAG3B,yEAIuC;AAHrC,qIAAA,0BAA0B,OAAA;AAC1B,yIAAA,8BAA8B,OAAA;AAGhC,6CAIyB;AAHvB,oHAAA,uBAAuB,OAAA;AAIzB,uDAAkE;AAAzD,4HAAA,0BAA0B,OAAA;AACnC,0EAK0C;AAJxC,4HAAA,mBAAmB,OAAA;AACnB,6HAAA,oBAAoB,OAAA;AAItB,4EAQ2C;AAPzC,kIAAA,wBAAwB,OAAA;AAQ1B,sFAIsD;AAHpD,4HAAA,mBAAmB,OAAA;AACnB,sIAAA,6BAA6B,OAAA;AAC7B,mIAAA,0BAA0B,OAAA;AAE5B,wFAKuD;AAJrD,8HAAA,oBAAoB,OAAA;AACpB,sIAAA,4BAA4B,OAAA;AAC5B,wIAAA,8BAA8B,OAAA;AAGhC,8DAK0C;AAJxC,iHAAA,oBAAoB,OAAA;AACpB,2GAAA,cAAc,OAAA;AAIhB,gGAW2D;AAVzD,+HAAA,iBAAiB,OAAA;AACjB,oIAAA,sBAAsB,OAAA;AACtB,4IAAA,8BAA8B,OAAA;AAC9B,+HAAA,iBAAiB,OAAA;AAQnB,0EAUgD;AAT9C,+HAAA,4BAA4B,OAAA;AAC5B,0HAAA,uBAAuB,OAAA;AACvB,4HAAA,yBAAyB,OAAA;AACzB,qIAAA,kCAAkC,OAAA;AAClC,gIAAA,6BAA6B,OAAA;AAM/B,kEAO4C;AAN1C,4HAAA,6BAA6B,OAAA;AAC7B,2GAAA,YAAY,OAAA;AACZ,qHAAA,sBAAsB,OAAA;AACtB,4HAAA,6BAA6B,OAAA;AAI/B,oEAQuC;AAPrC,sHAAA,gBAAgB,OAAA;AAChB,0HAAA,oBAAoB,OAAA;AACpB,wHAAA,kBAAkB,OAAA;AAClB,iIAAA,2BAA2B,OAAA;AAC3B,4HAAA,sBAAsB,OAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/lib/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/lib/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAQ9C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AA0CpD,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,mBAAmB,GAC1B,QAAQ,CAWV;AAeD,wBAAgB,+BAA+B,CAC7C,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,KAAK,CAAC,EAAE,MAAM,GACb,QAAQ,CAmCV"}
|
package/dist/lib/adapter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../src/lib/adapter.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../src/lib/adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { KernelState } from '@xemahq/kernel-contracts/kernel-state';
|
|
2
1
|
import { type EagerResolveOptions } from '@xemahq/service-registry-nest';
|
|
2
|
+
import type { KernelState } from '@xemahq/kernel-contracts/kernel-state';
|
|
3
3
|
export declare const ORG_DATABASE_POOL_SERVICE_NAME = "org-database-pool-api";
|
|
4
4
|
export type ControlPlaneDiscoveryOptions = EagerResolveOptions;
|
|
5
5
|
export declare function resolveControlPlaneBaseUrl(kernelState: KernelState, options?: ControlPlaneDiscoveryOptions): Promise<string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control-plane-discovery.d.ts","sourceRoot":"","sources":["../../src/lib/control-plane-discovery.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"control-plane-discovery.d.ts","sourceRoot":"","sources":["../../src/lib/control-plane-discovery.ts"],"names":[],"mappings":"AAaA,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAC;AAGzE,eAAO,MAAM,8BAA8B,0BAA0B,CAAC;AAGtE,MAAM,MAAM,4BAA4B,GAAG,mBAAmB,CAAC;AAQ/D,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,WAAW,EACxB,OAAO,CAAC,EAAE,4BAA4B,GACrC,OAAO,CAAC,MAAM,CAAC,CAMjB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control-plane-discovery.js","sourceRoot":"","sources":["../../src/lib/control-plane-discovery.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"control-plane-discovery.js","sourceRoot":"","sources":["../../src/lib/control-plane-discovery.ts"],"names":[],"mappings":";;;AAgCA,gEASC;AA5BD,yEAGuC;AAK1B,QAAA,8BAA8B,GAAG,uBAAuB,CAAC;AAWtE,SAAgB,0BAA0B,CACxC,WAAwB,EACxB,OAAsC;IAEtC,OAAO,IAAA,6CAAqB,EAC1B,WAAW,EACX,sCAA8B,EAC9B,OAAO,CACR,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"org-erasure.module.d.ts","sourceRoot":"","sources":["../../../src/lib/nest/org-erasure.module.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"org-erasure.module.d.ts","sourceRoot":"","sources":["../../../src/lib/nest/org-erasure.module.ts"],"names":[],"mappings":"AAoCA,OAAO,EAOL,KAAK,aAAa,EAClB,KAAK,IAAI,EACV,MAAM,gBAAgB,CAAC;AAKxB,OAAO,EAGL,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACtB,MAAM,iCAAiC,CAAC;AAMzC,eAAO,MAAM,kBAAkB,eAE9B,CAAC;AAUF,eAAO,MAAM,2BAA2B,0BAA0B,CAAC;AAGnE,eAAO,MAAM,sBAAsB,yBAAyB,CAAC;AAE7D,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACjD;AAED,qBAGa,oBAAoB;IAED,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,gBAAgB;IASvE,KAAK,CAAiB,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAGhE;AAED,MAAM,WAAW,uBAAwB,SAAQ,mBAAmB;IAMlE,QAAQ,CAAC,kBAAkB,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,MAAM,GAAG,MAAM,CAAC;CAC9D;AAQD,qBAAa,gBAAgB;IAC3B,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,uBAAuB,GAAG,aAAa;CAwChE"}
|
|
@@ -18,6 +18,7 @@ const swagger_1 = require("@nestjs/swagger");
|
|
|
18
18
|
const platform_common_1 = require("@xemahq/platform-common");
|
|
19
19
|
const xema_decorators_1 = require("@xemahq/xema-decorators");
|
|
20
20
|
const org_erasure_1 = require("../tenant-isolation/org-erasure");
|
|
21
|
+
const tenant_isolation_extension_1 = require("../tenant-isolation/tenant-isolation.extension");
|
|
21
22
|
exports.ORG_ERASURE_RUNNER = Symbol.for('@xemahq/biome-database-nest/org-erasure-runner');
|
|
22
23
|
exports.ORG_DATA_ERASURE_CAPABILITY = 'xema.org-data-erasure';
|
|
23
24
|
exports.ORG_ERASURE_ROUTE_PATH = 'internal/org-erasure';
|
|
@@ -58,9 +59,16 @@ class OrgErasureModule {
|
|
|
58
59
|
providers: [
|
|
59
60
|
{
|
|
60
61
|
provide: exports.ORG_ERASURE_RUNNER,
|
|
61
|
-
useFactory: (prisma) =>
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
useFactory: (prisma) => {
|
|
63
|
+
const client = prisma.asSystem();
|
|
64
|
+
const models = [
|
|
65
|
+
...(0, org_erasure_1.assertOrgErasureMatchesModels)(client, eraseOptions),
|
|
66
|
+
].sort();
|
|
67
|
+
new common_1.Logger(OrgErasureModule.name).log(`org-erasure participant armed on "${eraseOptions.orgField ?? tenant_isolation_extension_1.DEFAULT_ORG_FIELD}" over ${models.length} model(s): ${models.join(', ')}`);
|
|
68
|
+
return {
|
|
69
|
+
erase: (orgId) => (0, org_erasure_1.eraseOrgData)(prisma.asSystem(), orgId, eraseOptions),
|
|
70
|
+
};
|
|
71
|
+
},
|
|
64
72
|
inject: [prismaServiceToken],
|
|
65
73
|
},
|
|
66
74
|
],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"org-erasure.module.js","sourceRoot":"","sources":["../../../src/lib/nest/org-erasure.module.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"org-erasure.module.js","sourceRoot":"","sources":["../../../src/lib/nest/org-erasure.module.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAoCA,2CASwB;AACxB,6CAAwD;AACxD,6DAA4D;AAC5D,6DAAmF;AAEnF,iEAKyC;AACzC,+FAAmF;AAKtE,QAAA,kBAAkB,GAAG,MAAM,CAAC,GAAG,CAC1C,gDAAgD,CACjD,CAAC;AAUW,QAAA,2BAA2B,GAAG,uBAAuB,CAAC;AAGtD,QAAA,sBAAsB,GAAG,sBAAsB,CAAC;AAStD,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;IAEgB;IAD/C,YAC+C,MAAwB;QAAxB,WAAM,GAAN,MAAM,CAAkB;IACpE,CAAC;IAQJ,KAAK,CAAiB,KAAa;QACjC,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC;CACF,CAAA;AAdY,oDAAoB;AAW/B;IANC,IAAA,mCAAiB,EAAC,EAAE,QAAQ,EAAE,uCAAqB,CAAC,OAAO,EAAE,CAAC;IAC9D,IAAA,aAAI,EAAC,QAAQ,CAAC;IACd,IAAA,sBAAY,EAAC;QACZ,OAAO,EACL,6EAA6E;KAChF,CAAC;IACK,WAAA,IAAA,cAAK,EAAC,OAAO,CAAC,CAAA;;;;iDAEpB;+BAbU,oBAAoB;IAHhC,IAAA,iBAAO,EAAC,aAAa,CAAC;IACtB,IAAA,kBAAS,EAAC,mCAAiB,CAAC;IAC5B,IAAA,mBAAU,EAAC,sBAAsB,CAAC;IAG9B,WAAA,IAAA,eAAM,EAAC,0BAAkB,CAAC,CAAA;;GAFlB,oBAAoB,CAchC;AAiBD,MAAa,gBAAgB;IAC3B,MAAM,CAAC,OAAO,CAAC,OAAgC;QAC7C,MAAM,EAAE,kBAAkB,EAAE,GAAG,YAAY,EAAE,GAAG,OAAO,CAAC;QACxD,OAAO;YACL,MAAM,EAAE,gBAAgB;YACxB,WAAW,EAAE,CAAC,oBAAoB,CAAC;YACnC,SAAS,EAAE;gBACT;oBACE,OAAO,EAAE,0BAAkB;oBAC3B,UAAU,EAAE,CAAC,MAAwB,EAAoB,EAAE;wBACzD,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;wBAajC,MAAM,MAAM,GAAG;4BACb,GAAG,IAAA,2CAA6B,EAAC,MAAM,EAAE,YAAY,CAAC;yBACvD,CAAC,IAAI,EAAE,CAAC;wBACT,IAAI,eAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,GAAG,CACnC,qCACE,YAAY,CAAC,QAAQ,IAAI,8CAC3B,UAAU,MAAM,CAAC,MAAM,cAAc,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACzD,CAAC;wBACF,OAAO;4BACL,KAAK,EAAE,CAAC,KAAa,EAA6B,EAAE,CAClD,IAAA,0BAAY,EAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,YAAY,CAAC;yBACvD,CAAC;oBACJ,CAAC;oBACD,MAAM,EAAE,CAAC,kBAAkB,CAAC;iBAC7B;aACF;SACF,CAAC;IACJ,CAAC;CACF;AAzCD,4CAyCC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { OnModuleDestroy, OnModuleInit, Type } from '@nestjs/common';
|
|
2
1
|
import { TenantIsolationMode } from '../tenant-isolation/tenant-isolation-mode';
|
|
3
2
|
import { type UnscopedModelDeclarations } from '../tenant-isolation/unscoped-models';
|
|
3
|
+
import type { OnModuleDestroy, OnModuleInit, Type } from '@nestjs/common';
|
|
4
4
|
export type BiomePrismaClientCtor<TClient extends BiomePrismaClient> = new (...args: any[]) => TClient;
|
|
5
5
|
export interface BiomePrismaClient {
|
|
6
6
|
$connect(): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prisma-service-factory.d.ts","sourceRoot":"","sources":["../../../src/lib/nest/prisma-service-factory.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"prisma-service-factory.d.ts","sourceRoot":"","sources":["../../../src/lib/nest/prisma-service-factory.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,mBAAmB,EAEpB,MAAM,2CAA2C,CAAC;AAQnD,OAAO,EAEL,KAAK,yBAAyB,EAC/B,MAAM,qCAAqC,CAAC;AAE7C,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAY1E,MAAM,MAAM,qBAAqB,CAAC,OAAO,SAAS,iBAAiB,IAAI,KAIrE,GAAG,IAAI,EAAE,GAAG,EAAE,KACX,OAAO,CAAC;AAGb,MAAM,WAAW,iBAAiB;IAChC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAGD,MAAM,WAAW,6BAA6B;IAK5C,QAAQ,CAAC,IAAI,CAAC,EAAE,mBAAmB,CAAC;IAEpC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAK3B,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IA0B1C,QAAQ,CAAC,cAAc,CAAC,EAAE,yBAAyB,CAAC;CACrD;AAGD,MAAM,WAAW,+BAA+B;IAE9C,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,eAAe,CAAC,EAAE,6BAA6B,CAAC;CAC1D;AAMD,MAAM,WAAW,eAAe,CAAC,OAAO;IAOtC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IAM/B,QAAQ,IAAI,OAAO,CAAC;CACrB;AAGD,MAAM,MAAM,0BAA0B,CAAC,OAAO,IAAI,OAAO,GACvD,eAAe,CAAC,OAAO,CAAC,GACxB,YAAY,GACZ,eAAe,CAAC;AA2ElB,wBAAgB,wBAAwB,CAAC,OAAO,SAAS,iBAAiB,EACxE,gBAAgB,EAAE,qBAAqB,CAAC,OAAO,CAAC,EAChD,sBAAsB,CAAC,EAAE,MAAM,GAAG,+BAA+B,GAChE,IAAI,CAAC,0BAA0B,CAAC,OAAO,CAAC,CAAC,CAoL3C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prisma-service-factory.js","sourceRoot":"","sources":["../../../src/lib/nest/prisma-service-factory.ts"],"names":[],"mappings":";;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"prisma-service-factory.js","sourceRoot":"","sources":["../../../src/lib/nest/prisma-service-factory.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-name.js","sourceRoot":"","sources":["../../src/lib/schema-name.ts"],"names":[],"mappings":";;;AA8BA,sDA+BC;AA7DD,6CAIsB;AAMT,QAAA,oBAAoB,GAAG,SAAS,CAAC;AAE9C,MAAM,aAAa,GAAG,OAAO,CAAC;AAkB9B,SAAgB,qBAAqB,CAAC,OAAe,EAAE,KAAc;IACnE,MAAM,gBAAgB,GAAG,IAAA,sCAAyB,EAAC,OAAO,CAAC,CAAC;IAC5D,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CACb,mCAAmC,OAAO,oCAAoC,CAC/E,CAAC;IACJ,CAAC;IAED,MAAM,YAAY,GAChB,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE,IAAI,KAAK,KAAK,4BAAoB,CAAC;IACxE,MAAM,cAAc,GAAG,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAA,sCAAyB,EAAC,KAAK,CAAC,CAAC;IAE5E,IAAI,CAAC,YAAY,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CACb,iCAAiC,KAAK,oCAAoC,CAC3E,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,YAAY;QAC5B,CAAC,CAAC,GAAG,aAAa,IAAI,gBAAgB,EAAE;QACxC,CAAC,CAAC,GAAG,aAAa,IAAI,gBAAgB,KAAK,cAAc,EAAE,CAAC;IAI9D,MAAM,SAAS,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"schema-name.js","sourceRoot":"","sources":["../../src/lib/schema-name.ts"],"names":[],"mappings":";;;AA8BA,sDA+BC;AA7DD,6CAIsB;AAMT,QAAA,oBAAoB,GAAG,SAAS,CAAC;AAE9C,MAAM,aAAa,GAAG,OAAO,CAAC;AAkB9B,SAAgB,qBAAqB,CAAC,OAAe,EAAE,KAAc;IACnE,MAAM,gBAAgB,GAAG,IAAA,sCAAyB,EAAC,OAAO,CAAC,CAAC;IAC5D,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CACb,mCAAmC,OAAO,oCAAoC,CAC/E,CAAC;IACJ,CAAC;IAED,MAAM,YAAY,GAChB,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE,IAAI,KAAK,KAAK,4BAAoB,CAAC;IACxE,MAAM,cAAc,GAAG,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAA,sCAAyB,EAAC,KAAK,CAAC,CAAC;IAE5E,IAAI,CAAC,YAAY,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CACb,iCAAiC,KAAK,oCAAoC,CAC3E,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,YAAY;QAC5B,CAAC,CAAC,GAAG,aAAa,IAAI,gBAAgB,EAAE;QACxC,CAAC,CAAC,GAAG,aAAa,IAAI,gBAAgB,KAAK,cAAc,EAAE,CAAC;IAI9D,MAAM,SAAS,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAE9D,OAAO,IAAA,0BAAa,EAAC;QACnB,SAAS;QACT,SAAS,EAAE,2CAA8B;QACzC,SAAS,EAAE,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC;KAC/B,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -13,5 +13,12 @@ export declare class OrgErasureBlockedError extends Error {
|
|
|
13
13
|
readonly blockedModels: readonly string[];
|
|
14
14
|
constructor(orgId: string, blockedModels: readonly string[]);
|
|
15
15
|
}
|
|
16
|
+
export declare class OrgErasureMatchesNothingError extends Error {
|
|
17
|
+
readonly orgField: string;
|
|
18
|
+
readonly knownModels: readonly string[];
|
|
19
|
+
readonly exemptModels: readonly string[];
|
|
20
|
+
constructor(orgField: string, knownModels: readonly string[], exemptModels: readonly string[]);
|
|
21
|
+
}
|
|
22
|
+
export declare function assertOrgErasureMatchesModels(client: unknown, options?: EraseOrgDataOptions): ReadonlySet<string>;
|
|
16
23
|
export declare function eraseOrgData(client: unknown, orgId: string, options?: EraseOrgDataOptions): Promise<OrgErasureReport>;
|
|
17
24
|
//# sourceMappingURL=org-erasure.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"org-erasure.d.ts","sourceRoot":"","sources":["../../../src/lib/tenant-isolation/org-erasure.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"org-erasure.d.ts","sourceRoot":"","sources":["../../../src/lib/tenant-isolation/org-erasure.ts"],"names":[],"mappings":"AAmCA,MAAM,WAAW,mBAAmB;IAElC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAQ3B,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3C;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB,QAAQ,CAAC,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC1D,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAE9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAGD,qBAAa,sBAAuB,SAAQ,KAAK;IAE7C,QAAQ,CAAC,KAAK,EAAE,MAAM;IACtB,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE;gBADhC,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,SAAS,MAAM,EAAE;CAY5C;AAiBD,qBAAa,6BAA8B,SAAQ,KAAK;IAEpD,QAAQ,CAAC,QAAQ,EAAE,MAAM;IACzB,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE;IACvC,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE;gBAF/B,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,YAAY,EAAE,SAAS,MAAM,EAAE;CAkB3C;AAoBD,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,OAAO,EACf,OAAO,GAAE,mBAAwB,GAChC,WAAW,CAAC,MAAM,CAAC,CAYrB;AA2BD,wBAAsB,YAAY,CAChC,MAAM,EAAE,OAAO,EACf,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,gBAAgB,CAAC,CAwD3B"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.OrgErasureBlockedError = void 0;
|
|
3
|
+
exports.OrgErasureMatchesNothingError = exports.OrgErasureBlockedError = void 0;
|
|
4
|
+
exports.assertOrgErasureMatchesModels = assertOrgErasureMatchesModels;
|
|
4
5
|
exports.eraseOrgData = eraseOrgData;
|
|
5
6
|
const tenant_isolation_extension_1 = require("./tenant-isolation.extension");
|
|
6
7
|
const PRISMA_FK_VIOLATION_CODE = 'P2003';
|
|
@@ -18,6 +19,37 @@ class OrgErasureBlockedError extends Error {
|
|
|
18
19
|
}
|
|
19
20
|
}
|
|
20
21
|
exports.OrgErasureBlockedError = OrgErasureBlockedError;
|
|
22
|
+
class OrgErasureMatchesNothingError extends Error {
|
|
23
|
+
orgField;
|
|
24
|
+
knownModels;
|
|
25
|
+
exemptModels;
|
|
26
|
+
constructor(orgField, knownModels, exemptModels) {
|
|
27
|
+
super(`[org-erasure] this erasure participant matched ZERO models on org ` +
|
|
28
|
+
`field "${orgField}" — it cannot delete anything, so it MUST NOT ` +
|
|
29
|
+
`report a successful erasure (the orchestrator would record proof of ` +
|
|
30
|
+
`an erasure that never happened). Known models: [${knownModels.join(', ')}]` +
|
|
31
|
+
(exemptModels.length > 0
|
|
32
|
+
? `; exemptModels: [${exemptModels.join(', ')}]` +
|
|
33
|
+
` — exempting every org-scoped model leaves nothing to erase`
|
|
34
|
+
: '') +
|
|
35
|
+
`. Fix the participant's orgField (or stop registering the service as ` +
|
|
36
|
+
`an org-erasure participant) rather than relaxing this check.`);
|
|
37
|
+
this.orgField = orgField;
|
|
38
|
+
this.knownModels = knownModels;
|
|
39
|
+
this.exemptModels = exemptModels;
|
|
40
|
+
this.name = 'OrgErasureMatchesNothingError';
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
exports.OrgErasureMatchesNothingError = OrgErasureMatchesNothingError;
|
|
44
|
+
function assertOrgErasureMatchesModels(client, options = {}) {
|
|
45
|
+
const orgField = options.orgField ?? tenant_isolation_extension_1.DEFAULT_ORG_FIELD;
|
|
46
|
+
const exemptModels = options.exemptModels ?? [];
|
|
47
|
+
const scoped = (0, tenant_isolation_extension_1.collectOrgScopedModels)(client, orgField, exemptModels);
|
|
48
|
+
if (scoped.size === 0) {
|
|
49
|
+
throw new OrgErasureMatchesNothingError(orgField, Object.keys((0, tenant_isolation_extension_1.readRuntimeModels)(client)), exemptModels);
|
|
50
|
+
}
|
|
51
|
+
return scoped;
|
|
52
|
+
}
|
|
21
53
|
function delegateKeyForModel(modelName) {
|
|
22
54
|
return modelName.charAt(0).toLowerCase() + modelName.slice(1);
|
|
23
55
|
}
|
|
@@ -31,7 +63,7 @@ async function eraseOrgData(client, orgId, options = {}) {
|
|
|
31
63
|
if (orgId.trim() === '') {
|
|
32
64
|
throw new Error('[org-erasure] orgId must be a non-empty string.');
|
|
33
65
|
}
|
|
34
|
-
const scoped = (
|
|
66
|
+
const scoped = assertOrgErasureMatchesModels(client, options);
|
|
35
67
|
const deletedByModel = {};
|
|
36
68
|
let remaining = [...scoped];
|
|
37
69
|
let passes = 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"org-erasure.js","sourceRoot":"","sources":["../../../src/lib/tenant-isolation/org-erasure.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"org-erasure.js","sourceRoot":"","sources":["../../../src/lib/tenant-isolation/org-erasure.ts"],"names":[],"mappings":";;;AAoIA,sEAeC;AA2BD,oCA4DC;AAhND,6EAIsC;AAGtC,MAAM,wBAAwB,GAAG,OAAO,CAAC;AAyBzC,MAAa,sBAAuB,SAAQ,KAAK;IAEpC;IACA;IAFX,YACW,KAAa,EACb,aAAgC;QAEzC,KAAK,CACH,sCAAsC,KAAK,cAAc,aAAa,CAAC,IAAI,CACzE,IAAI,CACL,2EAA2E;YAC1E,2EAA2E;YAC3E,2EAA2E;YAC3E,0CAA0C,CAC7C,CAAC;QAVO,UAAK,GAAL,KAAK,CAAQ;QACb,kBAAa,GAAb,aAAa,CAAmB;QAUzC,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;IACvC,CAAC;CACF;AAfD,wDAeC;AAiBD,MAAa,6BAA8B,SAAQ,KAAK;IAE3C;IACA;IACA;IAHX,YACW,QAAgB,EAChB,WAA8B,EAC9B,YAA+B;QAExC,KAAK,CACH,oEAAoE;YAClE,UAAU,QAAQ,gDAAgD;YAClE,sEAAsE;YACtE,mDAAmD,WAAW,CAAC,IAAI,CACjE,IAAI,CACL,GAAG;YACJ,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC;gBACtB,CAAC,CAAC,oBAAoB,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;oBAC9C,6DAA6D;gBAC/D,CAAC,CAAC,EAAE,CAAC;YACP,uEAAuE;YACvE,8DAA8D,CACjE,CAAC;QAjBO,aAAQ,GAAR,QAAQ,CAAQ;QAChB,gBAAW,GAAX,WAAW,CAAmB;QAC9B,iBAAY,GAAZ,YAAY,CAAmB;QAgBxC,IAAI,CAAC,IAAI,GAAG,+BAA+B,CAAC;IAC9C,CAAC;CACF;AAtBD,sEAsBC;AAoBD,SAAgB,6BAA6B,CAC3C,MAAe,EACf,UAA+B,EAAE;IAEjC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,8CAAiB,CAAC;IACvD,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,EAAE,CAAC;IAChD,MAAM,MAAM,GAAG,IAAA,mDAAsB,EAAC,MAAM,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;IACtE,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,6BAA6B,CACrC,QAAQ,EACR,MAAM,CAAC,IAAI,CAAC,IAAA,8CAAiB,EAAC,MAAM,CAAC,CAAC,EACtC,YAAY,CACb,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAOD,SAAS,mBAAmB,CAAC,SAAiB;IAC5C,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAChE,CAAC;AAED,SAAS,qBAAqB,CAAC,KAAc;IAC3C,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACb,KAA4B,CAAC,IAAI,KAAK,wBAAwB,CAChE,CAAC;AACJ,CAAC;AAUM,KAAK,UAAU,YAAY,CAChC,MAAe,EACf,KAAa,EACb,UAA+B,EAAE;IAEjC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,8CAAiB,CAAC;IACvD,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACrE,CAAC;IAID,MAAM,MAAM,GAAG,6BAA6B,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAE9D,MAAM,cAAc,GAA2B,EAAE,CAAC;IAClD,IAAI,SAAS,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;IAC5B,IAAI,MAAM,GAAG,CAAC,CAAC;IAEf,OAAO,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,CAAC,CAAC;QACZ,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,IAAI,UAAU,GAAG,KAAK,CAAC;QAEvB,KAAK,MAAM,SAAS,IAAI,SAAS,EAAE,CAAC;YAClC,MAAM,QAAQ,GAAI,MAAkC,CAClD,mBAAmB,CAAC,SAAS,CAAC,CACG,CAAC;YACpC,IAAI,QAAQ,EAAE,UAAU,KAAK,SAAS,EAAE,CAAC;gBACvC,MAAM,IAAI,KAAK,CACb,mEAAmE;oBACjE,IAAI,SAAS,iBAAiB,mBAAmB,CAAC,SAAS,CAAC,KAAK,CACpE,CAAC;YACJ,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,QAAQ,CAAC,UAAU,CAAC;oBAC1C,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE;iBAC7B,CAAC,CAAC;gBACH,cAAc,CAAC,SAAS,CAAC,GAAG,CAAC,cAAc,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC;gBACrE,UAAU,GAAG,IAAI,CAAC;YACpB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,qBAAqB,CAAC,KAAK,CAAC,EAAE,CAAC;oBACjC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;oBACxB,SAAS;gBACX,CAAC;gBACD,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;QAED,IAAI,CAAC,UAAU,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtC,MAAM,IAAI,sBAAsB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACnD,CAAC;QACD,SAAS,GAAG,OAAO,CAAC;IACtB,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,MAAM,CACvD,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,EACnB,CAAC,CACF,CAAC;IACF,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC;AACzD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unscoped-models.d.ts","sourceRoot":"","sources":["../../../src/lib/tenant-isolation/unscoped-models.ts"],"names":[],"mappings":"AAmCA,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"unscoped-models.d.ts","sourceRoot":"","sources":["../../../src/lib/tenant-isolation/unscoped-models.ts"],"names":[],"mappings":"AAmCA,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAE9D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAQ1E,MAAM,WAAW,wBAAwB;IAMvC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAOxB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAGD,MAAM,MAAM,yBAAyB,GAAG,QAAQ,CAC9C,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,wBAAwB,CAAC,CAClD,CAAC;AAGF,MAAM,WAAW,kCAAkC;IACjD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAMD,qBAAa,6BAA8B,SAAQ,KAAK;IAEtD,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAEvC,QAAQ,CAAC,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;gBAG5C,UAAU,EAAE,SAAS,MAAM,EAAE,EAC7B,iBAAiB,EAAE,SAAS,MAAM,EAAE,EACpC,QAAQ,EAAE,MAAM;CASnB;AAMD,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,QAAQ,CACd,MAAM,CAAC,MAAM,EAAE;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE,CAAC,CAC1E,EACD,QAAQ,EAAE,MAAM,GACf,SAAS,MAAM,EAAE,CAKnB;AAQD,wBAAgB,kCAAkC,CAChD,YAAY,EAAE,yBAAyB,GACtC,SAAS,kCAAkC,EAAE,CA6B/C;AAGD,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,SAAS,MAAM,EAAE,EAC7B,iBAAiB,EAAE,SAAS,MAAM,EAAE,EACpC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,GACb,MAAM,CAgCR;AAED,MAAM,WAAW,2BAA2B;IAE1C,QAAQ,CAAC,MAAM,EAAE,QAAQ,CACvB,MAAM,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,SAAS;YAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;KAAE,CAAC,CAC1E,CAAC;IACF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IAEnC,QAAQ,CAAC,cAAc,EAAE,yBAAyB,CAAC;IAEnD,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;CACxC;AAiBD,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,2BAA2B,GACnC,IAAI,CAgDN"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unscoped-models.js","sourceRoot":"","sources":["../../../src/lib/tenant-isolation/unscoped-models.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"unscoped-models.js","sourceRoot":"","sources":["../../../src/lib/tenant-isolation/unscoped-models.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xemahq/biome-database-nest",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "Explicit database migration ownership, least-privilege runtime verification, and schema-qualified Prisma wiring for Xema biome services.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Neuralchowder Inc. <developer@xema.dev> (https://xema.dev)",
|
|
@@ -28,13 +28,14 @@
|
|
|
28
28
|
"@types/jest": "^30.0.0",
|
|
29
29
|
"@types/node": "25.2.3",
|
|
30
30
|
"@types/pg": "^8.16.0",
|
|
31
|
-
"@xemahq/identity-client": "^0.
|
|
32
|
-
"@xemahq/kernel-contracts": "^
|
|
31
|
+
"@xemahq/identity-client": "^0.7.0",
|
|
32
|
+
"@xemahq/kernel-contracts": "^1.2.0",
|
|
33
33
|
"@xemahq/xema-decorators": "^0.5.0",
|
|
34
34
|
"jest": "^30.3.0",
|
|
35
35
|
"prettier": "3.6.2",
|
|
36
36
|
"ts-jest": "^29.4.9",
|
|
37
37
|
"typescript": "5.9.3",
|
|
38
|
+
"@xemahq/platform-common": "^0.7.0",
|
|
38
39
|
"@xemahq/service-registry-nest": "0.5.0"
|
|
39
40
|
},
|
|
40
41
|
"peerDependencies": {
|
|
@@ -46,11 +47,11 @@
|
|
|
46
47
|
"@xemahq/identity-client": ">=0.4.0",
|
|
47
48
|
"@xemahq/kernel-contracts": ">=0.13.0",
|
|
48
49
|
"@xemahq/service-registry-nest": ">=0.2.0",
|
|
49
|
-
"@xemahq/xema-decorators": ">=0.2.0"
|
|
50
|
+
"@xemahq/xema-decorators": ">=0.2.0",
|
|
51
|
+
"@xemahq/platform-common": "^0.5.9 || ^0.6.0 || ^0.7.0"
|
|
50
52
|
},
|
|
51
53
|
"dependencies": {
|
|
52
54
|
"@xemahq/migration-runner-prisma": "^0.1.2",
|
|
53
|
-
"@xemahq/platform-common": "^0.6.1",
|
|
54
55
|
"pg": "8.16.3"
|
|
55
56
|
},
|
|
56
57
|
"exports": {
|
|
@@ -68,6 +69,7 @@
|
|
|
68
69
|
"clean": "rm -rf dist",
|
|
69
70
|
"build": "tsc -p tsconfig.build.json",
|
|
70
71
|
"format": "prettier --write \"src/**/*.ts\"",
|
|
72
|
+
"lint": "eslint .",
|
|
71
73
|
"test": "jest",
|
|
72
74
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
73
75
|
}
|
package/src/index.ts
CHANGED
|
@@ -97,8 +97,10 @@ export {
|
|
|
97
97
|
type UnscopedModelDeclarations,
|
|
98
98
|
} from './lib/tenant-isolation/unscoped-models';
|
|
99
99
|
export {
|
|
100
|
+
assertOrgErasureMatchesModels,
|
|
100
101
|
eraseOrgData,
|
|
101
102
|
OrgErasureBlockedError,
|
|
103
|
+
OrgErasureMatchesNothingError,
|
|
102
104
|
type EraseOrgDataOptions,
|
|
103
105
|
type OrgErasureReport,
|
|
104
106
|
} from './lib/tenant-isolation/org-erasure';
|
package/src/lib/adapter.ts
CHANGED
|
@@ -4,9 +4,10 @@ import {
|
|
|
4
4
|
ensureBiomeDbSearchPath,
|
|
5
5
|
} from '@xemahq/platform-common';
|
|
6
6
|
|
|
7
|
-
import type { BiomeDatabaseConfig } from './config';
|
|
8
7
|
import { resolveBiomeDatabaseConfigFromEnv } from './config';
|
|
9
8
|
|
|
9
|
+
import type { BiomeDatabaseConfig } from './config';
|
|
10
|
+
|
|
10
11
|
const DEFAULT_POOL_MAX = 3;
|
|
11
12
|
|
|
12
13
|
/**
|
|
@@ -47,7 +48,9 @@ function buildBiomeConnectionString(config: BiomeDatabaseConfig): string {
|
|
|
47
48
|
* Constructing the adapter correctly is the ONLY thing this function does, so
|
|
48
49
|
* the correct construction is the only construction a biome can perform.
|
|
49
50
|
*/
|
|
50
|
-
export function createBiomePrismaAdapter(
|
|
51
|
+
export function createBiomePrismaAdapter(
|
|
52
|
+
config: BiomeDatabaseConfig,
|
|
53
|
+
): PrismaPg {
|
|
51
54
|
const connectionString = buildBiomeConnectionString(config);
|
|
52
55
|
return new PrismaPg(
|
|
53
56
|
{
|
|
@@ -80,7 +83,7 @@ export function createBiomePrismaAdapterFromEnv(
|
|
|
80
83
|
const isDefault = dbKey === undefined || dbKey === '' || dbKey === 'primary';
|
|
81
84
|
const upperSuffix = isDefault
|
|
82
85
|
? ''
|
|
83
|
-
: `_${dbKey
|
|
86
|
+
: `_${dbKey.toUpperCase().replace(/[^A-Z0-9]/g, '_')}`;
|
|
84
87
|
|
|
85
88
|
const directUrl = env[`DATABASE_URL${upperSuffix}`];
|
|
86
89
|
const schema = env[`DB_SCHEMA${upperSuffix}`];
|
|
@@ -11,8 +11,12 @@
|
|
|
11
11
|
* (`KERNEL_STATE_TOKEN`) with bounded retry, because the app-wide registry is not
|
|
12
12
|
* yet hydrated at factory time. See that helper for the full rationale.
|
|
13
13
|
*/
|
|
14
|
+
import {
|
|
15
|
+
resolveHttpUrlEagerly,
|
|
16
|
+
type EagerResolveOptions,
|
|
17
|
+
} from '@xemahq/service-registry-nest';
|
|
18
|
+
|
|
14
19
|
import type { KernelState } from '@xemahq/kernel-contracts/kernel-state';
|
|
15
|
-
import { resolveHttpUrlEagerly, type EagerResolveOptions } from '@xemahq/service-registry-nest';
|
|
16
20
|
|
|
17
21
|
/** Registry name under which `org-database-pool-api` self-registers. */
|
|
18
22
|
export const ORG_DATABASE_POOL_SERVICE_NAME = 'org-database-pool-api';
|
|
@@ -30,5 +34,9 @@ export function resolveControlPlaneBaseUrl(
|
|
|
30
34
|
kernelState: KernelState,
|
|
31
35
|
options?: ControlPlaneDiscoveryOptions,
|
|
32
36
|
): Promise<string> {
|
|
33
|
-
return resolveHttpUrlEagerly(
|
|
37
|
+
return resolveHttpUrlEagerly(
|
|
38
|
+
kernelState,
|
|
39
|
+
ORG_DATABASE_POOL_SERVICE_NAME,
|
|
40
|
+
options,
|
|
41
|
+
);
|
|
34
42
|
}
|
|
@@ -25,10 +25,19 @@
|
|
|
25
25
|
*
|
|
26
26
|
* The org filter is applied inside {@link eraseOrgData}; the runner passes the
|
|
27
27
|
* unscoped client so scoping is neither doubled nor left to ambient context.
|
|
28
|
+
*
|
|
29
|
+
* **The module refuses to boot a participant that can erase nothing.** Wiring
|
|
30
|
+
* the runner asserts (via {@link assertOrgErasureMatchesModels}) that the
|
|
31
|
+
* configured `orgField` matches at least one model of THIS service's schema. A
|
|
32
|
+
* participant registered against a column its schema does not spell matches
|
|
33
|
+
* zero models, deletes nothing, and returns `{totalDeleted: 0}` — which the
|
|
34
|
+
* orchestrator records as a successful erasure. That must fail at deploy, not
|
|
35
|
+
* silently succeed during a Data Subject Request.
|
|
28
36
|
*/
|
|
29
37
|
import {
|
|
30
38
|
Controller,
|
|
31
39
|
Inject,
|
|
40
|
+
Logger,
|
|
32
41
|
Param,
|
|
33
42
|
Post,
|
|
34
43
|
UseGuards,
|
|
@@ -40,10 +49,12 @@ import { ServiceActorGuard } from '@xemahq/platform-common';
|
|
|
40
49
|
import { InternalRouteAudience, XemaInternalRoute } from '@xemahq/xema-decorators';
|
|
41
50
|
|
|
42
51
|
import {
|
|
52
|
+
assertOrgErasureMatchesModels,
|
|
43
53
|
eraseOrgData,
|
|
44
54
|
type EraseOrgDataOptions,
|
|
45
55
|
type OrgErasureReport,
|
|
46
56
|
} from '../tenant-isolation/org-erasure';
|
|
57
|
+
import { DEFAULT_ORG_FIELD } from '../tenant-isolation/tenant-isolation.extension';
|
|
47
58
|
|
|
48
59
|
import type { TenantScopedApi } from './prisma-service-factory';
|
|
49
60
|
|
|
@@ -112,10 +123,33 @@ export class OrgErasureModule {
|
|
|
112
123
|
providers: [
|
|
113
124
|
{
|
|
114
125
|
provide: ORG_ERASURE_RUNNER,
|
|
115
|
-
useFactory: (prisma: AsSystemProvider): OrgErasureRunner =>
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
126
|
+
useFactory: (prisma: AsSystemProvider): OrgErasureRunner => {
|
|
127
|
+
const client = prisma.asSystem();
|
|
128
|
+
// BOOT GATE. A participant whose orgField matches no model can
|
|
129
|
+
// never delete a row, and `eraseOrgData` would have answered every
|
|
130
|
+
// erasure `{totalDeleted: 0}` — which the orchestrator saga records
|
|
131
|
+
// as a successful erasure. Discovering that during a live Data
|
|
132
|
+
// Subject Request is discovering it too late, so the service
|
|
133
|
+
// refuses to START rather than advertise `xema.org-data-erasure`
|
|
134
|
+
// it cannot honour. Throwing here aborts Nest's bootstrap.
|
|
135
|
+
//
|
|
136
|
+
// This is the CONFIGURATION proof; `eraseOrgData` re-asserts per
|
|
137
|
+
// request, which is the proof of the RUN being recorded as
|
|
138
|
+
// evidence. The assertion is on MODELS matched — an org that
|
|
139
|
+
// genuinely holds no rows here still erases successfully.
|
|
140
|
+
const models = [
|
|
141
|
+
...assertOrgErasureMatchesModels(client, eraseOptions),
|
|
142
|
+
].sort();
|
|
143
|
+
new Logger(OrgErasureModule.name).log(
|
|
144
|
+
`org-erasure participant armed on "${
|
|
145
|
+
eraseOptions.orgField ?? DEFAULT_ORG_FIELD
|
|
146
|
+
}" over ${models.length} model(s): ${models.join(', ')}`,
|
|
147
|
+
);
|
|
148
|
+
return {
|
|
149
|
+
erase: (orgId: string): Promise<OrgErasureReport> =>
|
|
150
|
+
eraseOrgData(prisma.asSystem(), orgId, eraseOptions),
|
|
151
|
+
};
|
|
152
|
+
},
|
|
119
153
|
inject: [prismaServiceToken],
|
|
120
154
|
},
|
|
121
155
|
],
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { OnModuleDestroy, OnModuleInit, Type } from '@nestjs/common';
|
|
2
1
|
import { Injectable, Logger } from '@nestjs/common';
|
|
3
2
|
import { getAmbientOrgId } from '@xemahq/platform-common';
|
|
4
3
|
|
|
@@ -19,6 +18,8 @@ import {
|
|
|
19
18
|
type UnscopedModelDeclarations,
|
|
20
19
|
} from '../tenant-isolation/unscoped-models';
|
|
21
20
|
|
|
21
|
+
import type { OnModuleDestroy, OnModuleInit, Type } from '@nestjs/common';
|
|
22
|
+
|
|
22
23
|
/**
|
|
23
24
|
* Minimal structural shape of a generated Prisma `PrismaClient` as far as the
|
|
24
25
|
* lifecycle wrapper cares: it is a constructor whose single (optional) argument
|
|
@@ -306,7 +307,7 @@ export function createBiomePrismaService<TClient extends BiomePrismaClient>(
|
|
|
306
307
|
const value = Reflect.get(target, prop, target);
|
|
307
308
|
return typeof value === 'function' ? value.bind(target) : value;
|
|
308
309
|
},
|
|
309
|
-
})
|
|
310
|
+
});
|
|
310
311
|
}
|
|
311
312
|
|
|
312
313
|
const ambientClient = requireExtends()(
|
|
@@ -344,7 +345,7 @@ export function createBiomePrismaService<TClient extends BiomePrismaClient>(
|
|
|
344
345
|
const value = Reflect.get(target, prop, target);
|
|
345
346
|
return typeof value === 'function' ? value.bind(target) : value;
|
|
346
347
|
},
|
|
347
|
-
})
|
|
348
|
+
});
|
|
348
349
|
}
|
|
349
350
|
|
|
350
351
|
async onModuleInit(): Promise<void> {
|
package/src/lib/schema-name.ts
CHANGED
|
@@ -52,7 +52,7 @@ export function deriveBiomeSchemaName(biomeId: string, dbKey?: string): string {
|
|
|
52
52
|
|
|
53
53
|
// The hash covers the raw parts so the disambiguating suffix is stable across
|
|
54
54
|
// calls and distinguishes inputs that sanitise to the same prefix.
|
|
55
|
-
const hashParts = isDefaultKey ? [biomeId] : [biomeId, dbKey
|
|
55
|
+
const hashParts = isDefaultKey ? [biomeId] : [biomeId, dbKey];
|
|
56
56
|
|
|
57
57
|
return fitIdentifier({
|
|
58
58
|
candidate,
|
|
@@ -19,10 +19,15 @@
|
|
|
19
19
|
* row, or a cycle) blocks deletion — we FAIL LOUD with the blocked models
|
|
20
20
|
* rather than leave a silent partial erasure. Idempotent + resumable: re-running
|
|
21
21
|
* re-deletes already-gone rows as no-ops, so the orchestrator saga can retry.
|
|
22
|
+
*
|
|
23
|
+
* A participant that matches ZERO models is likewise a FAILURE, not a clean run
|
|
24
|
+
* — see {@link assertOrgErasureMatchesModels} for why, and for the distinction
|
|
25
|
+
* (models vs rows) that makes that assertion correct rather than a new bug.
|
|
22
26
|
*/
|
|
23
27
|
import {
|
|
24
28
|
DEFAULT_ORG_FIELD,
|
|
25
29
|
collectOrgScopedModels,
|
|
30
|
+
readRuntimeModels,
|
|
26
31
|
} from './tenant-isolation.extension';
|
|
27
32
|
|
|
28
33
|
/** Prisma's error code for a foreign-key constraint failure on delete. */
|
|
@@ -68,6 +73,80 @@ export class OrgErasureBlockedError extends Error {
|
|
|
68
73
|
}
|
|
69
74
|
}
|
|
70
75
|
|
|
76
|
+
/**
|
|
77
|
+
* Thrown when an erasure participant's configuration matches NO org-scoped
|
|
78
|
+
* model at all — it is structurally incapable of deleting anything.
|
|
79
|
+
*
|
|
80
|
+
* This is a MISCONFIGURATION, never an empty org. `memory-api` shipped as a
|
|
81
|
+
* registered GDPR erasure participant whose every model spells the org column
|
|
82
|
+
* `organizationId` while the participant was registered with no `orgField`, so
|
|
83
|
+
* {@link collectOrgScopedModels} returned an empty set, the delete loop never
|
|
84
|
+
* executed, and every erasure answered `200 {totalDeleted: 0}` — which the
|
|
85
|
+
* orchestrator saga records as a SUCCESSFUL erasure. A Data Subject Request
|
|
86
|
+
* answered from that record is false in writing.
|
|
87
|
+
*
|
|
88
|
+
* There is no degraded mode here: a participant that cannot delete anything
|
|
89
|
+
* must not be allowed to report success.
|
|
90
|
+
*/
|
|
91
|
+
export class OrgErasureMatchesNothingError extends Error {
|
|
92
|
+
constructor(
|
|
93
|
+
readonly orgField: string,
|
|
94
|
+
readonly knownModels: readonly string[],
|
|
95
|
+
readonly exemptModels: readonly string[],
|
|
96
|
+
) {
|
|
97
|
+
super(
|
|
98
|
+
`[org-erasure] this erasure participant matched ZERO models on org ` +
|
|
99
|
+
`field "${orgField}" — it cannot delete anything, so it MUST NOT ` +
|
|
100
|
+
`report a successful erasure (the orchestrator would record proof of ` +
|
|
101
|
+
`an erasure that never happened). Known models: [${knownModels.join(
|
|
102
|
+
', ',
|
|
103
|
+
)}]` +
|
|
104
|
+
(exemptModels.length > 0
|
|
105
|
+
? `; exemptModels: [${exemptModels.join(', ')}]` +
|
|
106
|
+
` — exempting every org-scoped model leaves nothing to erase`
|
|
107
|
+
: '') +
|
|
108
|
+
`. Fix the participant's orgField (or stop registering the service as ` +
|
|
109
|
+
`an org-erasure participant) rather than relaxing this check.`,
|
|
110
|
+
);
|
|
111
|
+
this.name = 'OrgErasureMatchesNothingError';
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Assert the participant can possibly delete something, and return the models
|
|
117
|
+
* it covers.
|
|
118
|
+
*
|
|
119
|
+
* **Models, never rows.** Zero MODELS matched means the participant is
|
|
120
|
+
* structurally incapable of erasing — a configuration defect. Zero ROWS deleted
|
|
121
|
+
* across a non-empty model set is a legitimate clean run: an org that genuinely
|
|
122
|
+
* holds no data in this service must succeed (and re-running an erasure must
|
|
123
|
+
* stay idempotent). Conflating the two would fail every honest erasure for an
|
|
124
|
+
* org with no data here, which is strictly worse than the bug this closes.
|
|
125
|
+
*
|
|
126
|
+
* Exported so a participant can gate at BOOT as well as per request:
|
|
127
|
+
* {@link OrgErasureModule} calls it while wiring its runner, so a service
|
|
128
|
+
* refuses to start rather than advertise `xema.org-data-erasure` it cannot
|
|
129
|
+
* honour. Boot proves the CONFIGURATION; the per-request call inside
|
|
130
|
+
* {@link eraseOrgData} proves the RUN that is about to be recorded as erasure
|
|
131
|
+
* evidence. Both are cheap and neither subsumes the other.
|
|
132
|
+
*/
|
|
133
|
+
export function assertOrgErasureMatchesModels(
|
|
134
|
+
client: unknown,
|
|
135
|
+
options: EraseOrgDataOptions = {},
|
|
136
|
+
): ReadonlySet<string> {
|
|
137
|
+
const orgField = options.orgField ?? DEFAULT_ORG_FIELD;
|
|
138
|
+
const exemptModels = options.exemptModels ?? [];
|
|
139
|
+
const scoped = collectOrgScopedModels(client, orgField, exemptModels);
|
|
140
|
+
if (scoped.size === 0) {
|
|
141
|
+
throw new OrgErasureMatchesNothingError(
|
|
142
|
+
orgField,
|
|
143
|
+
Object.keys(readRuntimeModels(client)),
|
|
144
|
+
exemptModels,
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
return scoped;
|
|
148
|
+
}
|
|
149
|
+
|
|
71
150
|
interface DeleteManyDelegate {
|
|
72
151
|
deleteMany(args: { where: Record<string, unknown> }): Promise<{ count: number }>;
|
|
73
152
|
}
|
|
@@ -103,11 +182,9 @@ export async function eraseOrgData(
|
|
|
103
182
|
throw new Error('[org-erasure] orgId must be a non-empty string.');
|
|
104
183
|
}
|
|
105
184
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
options.exemptModels ?? [],
|
|
110
|
-
);
|
|
185
|
+
// Matching no model is a misconfiguration, not an empty org — never let it
|
|
186
|
+
// return `{ totalDeleted: 0 }`, which the orchestrator reads as success.
|
|
187
|
+
const scoped = assertOrgErasureMatchesModels(client, options);
|
|
111
188
|
|
|
112
189
|
const deletedByModel: Record<string, number> = {};
|
|
113
190
|
let remaining = [...scoped];
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
* ─────────────────────────────────────────────────────────────────────────────
|
|
35
35
|
*/
|
|
36
36
|
import { TenantIsolationMode } from './tenant-isolation-mode';
|
|
37
|
+
|
|
37
38
|
import type { TenantIsolationLogger } from './tenant-isolation.extension';
|
|
38
39
|
|
|
39
40
|
/**
|
|
@@ -99,7 +100,9 @@ export class UndeclaredUnscopedModelsError extends Error {
|
|
|
99
100
|
* `orgField` — the set the isolation extension can never auto-scope.
|
|
100
101
|
*/
|
|
101
102
|
export function collectUnscopableModels(
|
|
102
|
-
models: Readonly<
|
|
103
|
+
models: Readonly<
|
|
104
|
+
Record<string, { readonly fields: readonly { readonly name: string }[] }>
|
|
105
|
+
>,
|
|
103
106
|
orgField: string,
|
|
104
107
|
): readonly string[] {
|
|
105
108
|
return Object.entries(models)
|