@stratum-hq/lib 1.7.0 → 1.8.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.
Files changed (59) hide show
  1. package/README.md +29 -2
  2. package/dist/crypto.d.ts.map +1 -1
  3. package/dist/crypto.js +50 -10
  4. package/dist/crypto.js.map +1 -1
  5. package/dist/index.d.ts +7 -3
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +17 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/migrate-schemas.d.ts +4 -0
  10. package/dist/migrate-schemas.d.ts.map +1 -1
  11. package/dist/migrate-schemas.js +16 -6
  12. package/dist/migrate-schemas.js.map +1 -1
  13. package/dist/migrate.d.ts +24 -0
  14. package/dist/migrate.d.ts.map +1 -1
  15. package/dist/migrate.js +44 -6
  16. package/dist/migrate.js.map +1 -1
  17. package/dist/migration-sql.d.ts +25 -0
  18. package/dist/migration-sql.d.ts.map +1 -0
  19. package/dist/migration-sql.js +64 -0
  20. package/dist/migration-sql.js.map +1 -0
  21. package/dist/migrations/029_tenant_parent_cycle_guard.sql +2 -2
  22. package/dist/migrations/031_subtree_read_scope.sql +6 -6
  23. package/dist/migrations/032_control_role.sql +809 -0
  24. package/dist/migrations/033_api_keys_tenant_index.sql +14 -0
  25. package/dist/pinned-query.d.ts +29 -0
  26. package/dist/pinned-query.d.ts.map +1 -0
  27. package/dist/pinned-query.js +60 -0
  28. package/dist/pinned-query.js.map +1 -0
  29. package/dist/pool-helpers.d.ts +2 -0
  30. package/dist/pool-helpers.d.ts.map +1 -1
  31. package/dist/pool-helpers.js +17 -3
  32. package/dist/pool-helpers.js.map +1 -1
  33. package/dist/role-model.d.ts +178 -0
  34. package/dist/role-model.d.ts.map +1 -0
  35. package/dist/role-model.js +670 -0
  36. package/dist/role-model.js.map +1 -0
  37. package/dist/services/api-key-service.d.ts +12 -2
  38. package/dist/services/api-key-service.d.ts.map +1 -1
  39. package/dist/services/api-key-service.js +33 -9
  40. package/dist/services/api-key-service.js.map +1 -1
  41. package/dist/services/config-service.d.ts +15 -6
  42. package/dist/services/config-service.d.ts.map +1 -1
  43. package/dist/services/config-service.js +96 -50
  44. package/dist/services/config-service.js.map +1 -1
  45. package/dist/services/tenant-service.d.ts.map +1 -1
  46. package/dist/services/tenant-service.js +4 -4
  47. package/dist/services/tenant-service.js.map +1 -1
  48. package/dist/stratum-policies.d.ts +51 -0
  49. package/dist/stratum-policies.d.ts.map +1 -0
  50. package/dist/stratum-policies.js +217 -0
  51. package/dist/stratum-policies.js.map +1 -0
  52. package/dist/stratum-tables.d.ts.map +1 -1
  53. package/dist/stratum-tables.js +1 -0
  54. package/dist/stratum-tables.js.map +1 -1
  55. package/dist/stratum.d.ts +52 -7
  56. package/dist/stratum.d.ts.map +1 -1
  57. package/dist/stratum.js +75 -14
  58. package/dist/stratum.js.map +1 -1
  59. package/package.json +5 -5
package/README.md CHANGED
@@ -38,17 +38,44 @@ const permissions = await stratum.resolvePermissions(customer.id);
38
38
 
39
39
  The `pool` is **borrowed, not owned**: Stratum never creates or closes it. With `autoMigrate: true`, `initialize()` runs the schema migrations on first start; leave it off and manage migrations yourself via `migrate`.
40
40
 
41
+ ## Admin pool and the control role (1.8, opt-in)
42
+
43
+ Migration 032 adds a NOLOGIN **control role** (`stratum_control` by default). Every Stratum table has a `stratum_control_plane` policy for that role, so a login that is a member of it reaches every row, and a session cannot become a member by setting anything. Give the library its own pool on such a login, and keep `pool` for your application:
44
+
45
+ ```typescript
46
+ const adminPool = new Pool({ connectionString: process.env.DATABASE_ADMIN_URL }); // member of stratum_control
47
+ const pool = new Pool({ connectionString: process.env.DATABASE_URL }); // the application role
48
+ const stratum = new Stratum({ adminPool, pool, autoMigrate: true, enforceRls: true });
49
+ ```
50
+
51
+ - Every library query and `autoMigrate` run on `adminPool`. The admin login needs neither SUPERUSER nor BYPASSRLS.
52
+ - `initialize()` checks both logins: the admin login must be a member of the control role; the application login must not be a superuser, have BYPASSRLS, be a member of the control role, own Stratum tables or functions, write any Stratum table, or read `api_keys`, `webhooks`, `regions` or `stratum_security`. It warns about each problem; with `enforceRls: true` a problem with the application login throws.
53
+ - `bootstrapRolesSql({ adminRole, appRole, controlRole })` returns the idempotent SQL a database administrator runs once (and again after a migration that adds a table): it creates the control role, makes the admin login a member, and limits the application login to `SELECT` on the read-list tables (`APP_READ_TABLES`). `stratum db roles` (`@stratum-hq/cli`) prints it, or applies it with `--apply`. It first stops when the Stratum tables carry objects the migrations did not create (rules, triggers or defaults that call other functions, changed Stratum functions), because such objects would run with the rights of the login that applies it, and later of the admin login.
54
+ - Applying the control role (`stratum_apply_control_role()`, run by migration 032 and by the bootstrap SQL) resets row-level security on every Stratum table: it drops all their policies, enables and forces RLS, and re-creates the canonical policies. `stratumPolicyDrift(pool)` reports how a database differs from that set; `stratum doctor` shows it.
55
+ - `inspectRoleModel({ appPool, adminPool })` returns the role-model checks as data, without logging, for your own health checks. `stratum doctor` and `stratum health` use it.
56
+ - Migration 032 creates and joins the control role itself only with the opt-in `applyControlRole: true` (`migrate()`, `migrateAllSchemas()`; `autoMigrate` sets it when it runs on `adminPool`), or when the migrating login is a superuser or already a member, and only when the migrating role can (CREATEROLE, or ADMIN on an existing role). Set the opt-in only for the admin login: it makes the migrating login a member of the control role. Otherwise 032 still completes: it applies everything that needs no role, skips the control role with a WARNING that prints the bootstrap SQL, and the database keeps the pre-1.8 behavior. `initialize()` and `stratum doctor` then report the hardening as not active. Running the bootstrap SQL as a superuser later applies it through the idempotent `stratum_apply_control_role(role_name, schema)` function that 032 installs.
57
+ - Migrations 029 and 031 created helper functions with `SET app.*` clauses, which PostgreSQL accepts only from a superuser. When the migrating role is not a superuser, `migrate()` drops those clause lines from these two files; 032 re-creates both functions without them when it applies the control role.
58
+ - The control role name: `migrate({ controlRole })`, `migrateAllSchemas({ controlRole })` and `new Stratum({ controlRole })` set it, and so does `ALTER DATABASE ... SET stratum.control_role = '...'` for every session of one database. Without either, the migration reuses the role the database already has, else `stratum_control`. Roles are cluster-wide, so give databases that must stay apart their own name.
59
+ - The legacy `app.bypass_rls` path stays open while `stratum_security.legacy_guc_bypass` is true, the 1.8 default. Once every client of the database uses `adminPool`, close it as a member of the control role with `stratum db lock` (or `UPDATE stratum_security SET legacy_guc_bypass = false`).
60
+ - Known limit: the tenant context is still the session setting `app.current_tenant_id`, so SQL that runs as the application login can choose a tenant id it knows and read that tenant's rows in the read-list tables. The role model keeps credentials and the bypass out of its reach, not a chosen tenant context.
61
+ - Step by step, including managed PostgreSQL: the [hardening guide](https://docs.stratum-hq.org/guides/hardening-roles/).
62
+ - Without `adminPool`, Stratum behaves as before and logs a deprecation warning once. `adminPool` becomes required in 2.0, which also removes the legacy path.
63
+
64
+ ### API key hashes
65
+
66
+ Keys created before `STRATUM_API_KEY_HMAC_SECRET` was set carry an unkeyed SHA-256 hash (version 1). In 1.x, `validateApiKey` still accepts them by default (`allowLegacyKeyHashes: true`) and re-hashes each one with HMAC when it authenticates, logging a warning once per process. Set `allowLegacyKeyHashes: false` to accept only HMAC hashes once the secret is set; 2.0 makes that the default. Before upgrading to 2.0, rotate the keys that still have a version 1 hash (`SELECT id, name FROM api_keys WHERE hash_version = 1 AND revoked_at IS NULL`).
67
+
41
68
  ## API Summary
42
69
 
43
70
  The `Stratum` instance covers the full tenant lifecycle:
44
71
 
45
72
  - **Tenants**: `createTenant`, `getTenant`, `listTenants`, `updateTenant`, `moveTenant`, `getAncestors`, `getDescendants`, `batchCreateTenants`
46
- - **Config**: `resolveConfig`, `setConfig`, `deleteConfig`, `batchSetConfig`, `diffConfig`
73
+ - **Config**: `resolveConfig`, `setConfig`, `deleteConfig`, `batchSetConfig`, `diffConfig`. A sensitive value inherited from an ancestor resolves masked (`value: null`, `masked: true`); pass `{ revealSensitive: true }` in trusted server code that needs the secret.
47
74
  - **Permissions & ABAC**: `resolvePermissions`, `createPermission`, `createAbacPolicy`, `evaluateAbac`
48
75
  - **API keys & roles**: `createApiKey`, `validateApiKey`, `rotateApiKey`, `createRole`, `assignRoleToKey`
49
76
  - **Webhooks & audit**: `createWebhook`, `testWebhook`, `queryAuditLogs`, `listFailedDeliveries`
50
77
  - **GDPR & regions**: `exportTenantData`, `purgeTenant`, `grantConsent`, `createRegion`, `migrateRegion`
51
- - **Usage metering**: `recordUsage`, `aggregateUsage` (see [docs/usage-metering.md](../../docs/usage-metering.md))
78
+ - **Usage metering**: `recordUsage`, `aggregateUsage` (see [docs/usage-metering.md](https://github.com/stratum-hq/Stratum/blob/main/docs/usage-metering.md))
52
79
 
53
80
  Low-level pool helpers are also exported:
54
81
 
@@ -1 +1 @@
1
- {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AAyFA,qFAAqF;AACrF,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED;;;2FAG2F;AAC3F,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAejD;AAED;;0EAE0E;AAC1E,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAEvG;AAED;;+EAE+E;AAC/E,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM9G"}
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AA+HA,qFAAqF;AACrF,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED;;;2FAG2F;AAC3F,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAkBjD;AAED;;0EAE0E;AAC1E,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAEvG;AAED;;+EAE+E;AAC/E,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM9G"}
package/dist/crypto.js CHANGED
@@ -8,6 +8,7 @@ exports.decrypt = decrypt;
8
8
  exports.encryptWithKeyMaterial = encryptWithKeyMaterial;
9
9
  exports.decryptWithKeyMaterial = decryptWithKeyMaterial;
10
10
  const node_crypto_1 = __importDefault(require("node:crypto"));
11
+ const core_1 = require("@stratum-hq/core");
11
12
  const ALGORITHM = "aes-256-gcm";
12
13
  const IV_LENGTH = 12;
13
14
  const AUTH_TAG_LENGTH = 16;
@@ -25,30 +26,65 @@ function nodeEnvRequiringKeyMaterial() {
25
26
  // salt is not secret; the key material is. Every other environment requires an
26
27
  // explicit STRATUM_HKDF_SALT.
27
28
  const NON_PRODUCTION_DEFAULT_SALT = "stratum-non-production-hkdf-salt-v1";
29
+ // Development and test only fallback key material.
30
+ const NON_PRODUCTION_DEFAULT_KEY = "stratum-dev-key";
31
+ // The shortest STRATUM_ENCRYPTION_KEY accepted outside development and test.
32
+ const MIN_KEY_BYTES = 32;
33
+ // The format of STRATUM_HKDF_SALT. Buffer.from(salt, "hex") silently shortens any other string.
34
+ const HEX_SALT = /^(?:[0-9a-fA-F]{2})+$/;
28
35
  const HKDF_SALT = (() => {
29
- if (process.env.STRATUM_HKDF_SALT) {
30
- return Buffer.from(process.env.STRATUM_HKDF_SALT, "hex");
31
- }
32
36
  const strictEnv = nodeEnvRequiringKeyMaterial();
37
+ const salt = process.env.STRATUM_HKDF_SALT;
38
+ if (salt) {
39
+ if (!HEX_SALT.test(salt)) {
40
+ throw new Error("STRATUM_HKDF_SALT must be a non-empty, even-length hex string");
41
+ }
42
+ const bytes = Buffer.from(salt, "hex");
43
+ if (strictEnv && bytes.equals(Buffer.from(NON_PRODUCTION_DEFAULT_SALT, "utf8"))) {
44
+ throw new Error(`STRATUM_HKDF_SALT is the built-in development salt; set a random salt in ${strictEnv}`);
45
+ }
46
+ return bytes;
47
+ }
33
48
  if (strictEnv) {
34
49
  throw new Error(`STRATUM_HKDF_SALT must be set in ${strictEnv}`);
35
50
  }
36
51
  return Buffer.from(NON_PRODUCTION_DEFAULT_SALT, "utf8");
37
52
  })();
53
+ // Outside development and test, the key is checked when the module loads, so
54
+ // a deployment without usable key material refuses to start instead of failing
55
+ // on its first sensitive operation.
56
+ (() => {
57
+ const strictEnv = nodeEnvRequiringKeyMaterial();
58
+ if (!strictEnv)
59
+ return;
60
+ const key = process.env.STRATUM_ENCRYPTION_KEY;
61
+ if (!key) {
62
+ throw new Error(`STRATUM_ENCRYPTION_KEY must be set in ${strictEnv}` +
63
+ (process.env.WEBHOOK_ENCRYPTION_KEY
64
+ ? ". WEBHOOK_ENCRYPTION_KEY is read only in development and test; set STRATUM_ENCRYPTION_KEY to its value"
65
+ : ""));
66
+ }
67
+ if (key === NON_PRODUCTION_DEFAULT_KEY) {
68
+ throw new Error(`STRATUM_ENCRYPTION_KEY is the built-in development key; set random key material in ${strictEnv}`);
69
+ }
70
+ if (Buffer.byteLength(key, "utf8") < MIN_KEY_BYTES) {
71
+ throw new Error(`STRATUM_ENCRYPTION_KEY must be at least ${MIN_KEY_BYTES} bytes in ${strictEnv}`);
72
+ }
73
+ })();
38
74
  function hkdfDeriveKey(keyMaterial, salt = HKDF_SALT, info = "stratum-aes-key") {
39
75
  return Buffer.from(node_crypto_1.default.hkdfSync("sha256", Buffer.from(keyMaterial, "utf8"), salt, info, 32));
40
76
  }
41
77
  function getEncryptionKeyMaterial() {
42
- const envKey = process.env.STRATUM_ENCRYPTION_KEY ?? process.env.WEBHOOK_ENCRYPTION_KEY;
78
+ const strictEnv = nodeEnvRequiringKeyMaterial();
79
+ // WEBHOOK_ENCRYPTION_KEY is a legacy name, read only in development and test.
80
+ const envKey = process.env.STRATUM_ENCRYPTION_KEY ?? (strictEnv ? undefined : process.env.WEBHOOK_ENCRYPTION_KEY);
43
81
  if (envKey) {
44
82
  return envKey;
45
83
  }
46
- const strictEnv = nodeEnvRequiringKeyMaterial();
47
84
  if (strictEnv) {
48
85
  throw new Error(`STRATUM_ENCRYPTION_KEY must be set in ${strictEnv}`);
49
86
  }
50
- // Development and test only fallback
51
- return "stratum-dev-key";
87
+ return NON_PRODUCTION_DEFAULT_KEY;
52
88
  }
53
89
  function getEncryptionKey() {
54
90
  return hkdfDeriveKey(getEncryptionKeyMaterial());
@@ -76,7 +112,7 @@ function decryptWithKey(encrypted, key) {
76
112
  [ivHex, authTagHex, ciphertextHex] = parts;
77
113
  }
78
114
  else {
79
- throw new Error("Invalid encrypted value format");
115
+ throw new core_1.DecryptionError("format");
80
116
  }
81
117
  const iv = Buffer.from(ivHex, "hex");
82
118
  const authTag = Buffer.from(authTagHex, "hex");
@@ -105,10 +141,14 @@ function decrypt(encrypted) {
105
141
  return decryptWithKey(encrypted, deriveKey(previousKey || getEncryptionKeyMaterial(), previousSalt));
106
142
  }
107
143
  catch {
108
- // Both pairs failed: throw the original error
144
+ // Both pairs failed: report the original error
109
145
  }
110
146
  }
111
- throw err;
147
+ if (err instanceof core_1.DecryptionError)
148
+ throw err;
149
+ // Node reports a failed GCM authentication as "Unsupported state or
150
+ // unable to authenticate data", which does not say what to check.
151
+ throw new core_1.DecryptionError("authentication", { cause: err });
112
152
  }
113
153
  }
114
154
  /** Encrypts a value with the key derived from `keyMaterial` and `saltHex`.
@@ -1 +1 @@
1
- {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -2,15 +2,19 @@ export { Stratum, type StratumOptions } from "./stratum.js";
2
2
  export { migrate, type MigrateOptions } from "./migrate.js";
3
3
  export { migrateAllSchemas, type MigrateSchemasOptions, type MigrateSchemasResult, } from "./migrate-schemas.js";
4
4
  export { STRATUM_TABLES } from "./stratum-tables.js";
5
+ export { STRATUM_CONTROL_ROLE } from "./migration-sql.js";
6
+ export { PINNED_SEARCH_PATH, pinnedQuery, schemaOfTable, withPinnedSearchPath } from "./pinned-query.js";
7
+ export { stratumPolicyDrift, STRATUM_RLS_TABLES, type PolicyDriftOptions, } from "./stratum-policies.js";
8
+ export { bootstrapRolesSql, inspectRoleModel, APP_READ_TABLES, type BootstrapRolesOptions, type RoleModelReport, type InspectRoleModelOptions, } from "./role-model.js";
5
9
  export { withClient, withTransaction } from "./pool-helpers.js";
6
10
  export { runScopedJob, type ScopedJobFn, type RunScopedJobOptions, } from "./scoped-job.js";
7
11
  export { verifyWebhookSignature, signWebhookPayload, DEFAULT_WEBHOOK_TOLERANCE_SECONDS, type VerifyWebhookOptions, } from "./webhook-signature.js";
8
12
  export { traced, getTracer, isTracingEnabled } from "./telemetry.js";
9
- export { ErrorCode, StratumError, TenantNotFoundError, TenantAlreadyExistsError, TenantHasChildrenError, TenantCycleDetectedError, TenantArchivedError, TenantSuspendedError, TenantPendingError, TenantProvisioningError, InvalidTenantStateError, TenantContextNotFoundError, IsolationViolationError, IsolationStrategyUnsupportedError, PermissionLockedError, PermissionNotFoundError, PermissionRevocationDeniedError, ConfigLockedError, ConfigNotFoundError, ValidationError, UnauthorizedError, ForbiddenError, RegionInUseError, RegionNotActiveError, WebhookNotFoundError, WebhookDeliveryError, WebhookUrlValidationError, RegionNotFoundError, AbacPolicyNotFoundError, InvalidAbacOperatorError, AbacPolicyLockedError, } from "@stratum-hq/core";
10
- export type { TenantNode, TenantContext, CreateTenantInput, UpdateTenantInput, MoveTenantInput, PaginationInput, PaginatedResult, ConfigEntry, SetConfigInput, BatchSetConfigEntry, ResolvedConfigEntry, ResolvedConfig, PermissionPolicy, CreatePermissionInput, UpdatePermissionInput, ResolvedPermission, } from "@stratum-hq/core";
13
+ export { ErrorCode, StratumError, TenantNotFoundError, TenantAlreadyExistsError, TenantHasChildrenError, TenantCycleDetectedError, TenantArchivedError, TenantSuspendedError, TenantPendingError, TenantProvisioningError, InvalidTenantStateError, TenantContextNotFoundError, IsolationViolationError, IsolationStrategyUnsupportedError, PermissionLockedError, PermissionNotFoundError, PermissionRevocationDeniedError, ConfigLockedError, ConfigNotFoundError, ValidationError, UnauthorizedError, ForbiddenError, RegionInUseError, RegionNotActiveError, WebhookNotFoundError, WebhookDeliveryError, WebhookUrlValidationError, RegionNotFoundError, AbacPolicyNotFoundError, InvalidAbacOperatorError, AbacPolicyLockedError, DecryptionError, } from "@stratum-hq/core";
14
+ export type { TenantNode, TenantContext, CreateTenantInput, UpdateTenantInput, MoveTenantInput, PaginationInput, PaginatedResult, ConfigEntry, SetConfigInput, BatchSetConfigEntry, ResolvedConfigEntry, ResolveConfigOptions, ResolvedConfig, PermissionPolicy, CreatePermissionInput, UpdatePermissionInput, ResolvedPermission, } from "@stratum-hq/core";
11
15
  export { RateLimiter, MemoryRateLimitStore } from "./services/rate-limit-service.js";
12
16
  export type { RateLimit, RateLimitResult, RateLimitState, RateLimitStore, RateLimitResolver, RateLimiterOptions, } from "./services/rate-limit-service.js";
13
- export type { ApiKeyRecord, CreatedApiKey, ValidatedApiKey, CreateApiKeyOptions } from "./services/api-key-service.js";
17
+ export type { ApiKeyRecord, CreatedApiKey, ValidatedApiKey, CreateApiKeyOptions, ValidateApiKeyOptions, } from "./services/api-key-service.js";
14
18
  export type { BatchCreateResult } from "./services/tenant-service.js";
15
19
  export type { KeyRotationResult, KeyRotationSalts, KeyRotationUnreadableRow } from "./services/key-rotation-service.js";
16
20
  export type { DeliveryStats } from "./services/event-service.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EACL,iBAAiB,EACjB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,GAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EACL,YAAY,EACZ,KAAK,WAAW,EAChB,KAAK,mBAAmB,GACzB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,iCAAiC,EACjC,KAAK,oBAAoB,GAC1B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAKrE,OAAO,EACL,SAAS,EACT,YAAY,EACZ,mBAAmB,EACnB,wBAAwB,EACxB,sBAAsB,EACtB,wBAAwB,EACxB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,uBAAuB,EACvB,uBAAuB,EACvB,0BAA0B,EAC1B,uBAAuB,EACvB,iCAAiC,EACjC,qBAAqB,EACrB,uBAAuB,EACvB,+BAA+B,EAC/B,iBAAiB,EACjB,mBAAmB,EACnB,eAAe,EACf,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,yBAAyB,EACzB,mBAAmB,EACnB,uBAAuB,EACvB,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAG1B,YAAY,EACV,UAAU,EACV,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,eAAe,EACf,WAAW,EACX,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,cAAc,EACd,gBAAgB,EAChB,qBAAqB,EACrB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACrF,YAAY,EACV,SAAS,EACT,eAAe,EACf,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,kCAAkC,CAAC;AAE1C,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACvH,YAAY,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACtE,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAC;AACxH,YAAY,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACjE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAGzF,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAGvG,YAAY,EACV,gBAAgB,EAChB,UAAU,EACV,cAAc,EACd,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.noopLogger = exports.defaultLogger = exports.MemoryRateLimitStore = exports.RateLimiter = exports.AbacPolicyLockedError = exports.InvalidAbacOperatorError = exports.AbacPolicyNotFoundError = exports.RegionNotFoundError = exports.WebhookUrlValidationError = exports.WebhookDeliveryError = exports.WebhookNotFoundError = exports.RegionNotActiveError = exports.RegionInUseError = exports.ForbiddenError = exports.UnauthorizedError = exports.ValidationError = exports.ConfigNotFoundError = exports.ConfigLockedError = exports.PermissionRevocationDeniedError = exports.PermissionNotFoundError = exports.PermissionLockedError = exports.IsolationStrategyUnsupportedError = exports.IsolationViolationError = exports.TenantContextNotFoundError = exports.InvalidTenantStateError = exports.TenantProvisioningError = exports.TenantPendingError = exports.TenantSuspendedError = exports.TenantArchivedError = exports.TenantCycleDetectedError = exports.TenantHasChildrenError = exports.TenantAlreadyExistsError = exports.TenantNotFoundError = exports.StratumError = exports.ErrorCode = exports.isTracingEnabled = exports.getTracer = exports.traced = exports.DEFAULT_WEBHOOK_TOLERANCE_SECONDS = exports.signWebhookPayload = exports.verifyWebhookSignature = exports.runScopedJob = exports.withTransaction = exports.withClient = exports.STRATUM_TABLES = exports.migrateAllSchemas = exports.migrate = exports.Stratum = void 0;
3
+ exports.WebhookUrlValidationError = exports.WebhookDeliveryError = exports.WebhookNotFoundError = exports.RegionNotActiveError = exports.RegionInUseError = exports.ForbiddenError = exports.UnauthorizedError = exports.ValidationError = exports.ConfigNotFoundError = exports.ConfigLockedError = exports.PermissionRevocationDeniedError = exports.PermissionNotFoundError = exports.PermissionLockedError = exports.IsolationStrategyUnsupportedError = exports.IsolationViolationError = exports.TenantContextNotFoundError = exports.InvalidTenantStateError = exports.TenantProvisioningError = exports.TenantPendingError = exports.TenantSuspendedError = exports.TenantArchivedError = exports.TenantCycleDetectedError = exports.TenantHasChildrenError = exports.TenantAlreadyExistsError = exports.TenantNotFoundError = exports.StratumError = exports.ErrorCode = exports.isTracingEnabled = exports.getTracer = exports.traced = exports.DEFAULT_WEBHOOK_TOLERANCE_SECONDS = exports.signWebhookPayload = exports.verifyWebhookSignature = exports.runScopedJob = exports.withTransaction = exports.withClient = exports.APP_READ_TABLES = exports.inspectRoleModel = exports.bootstrapRolesSql = exports.STRATUM_RLS_TABLES = exports.stratumPolicyDrift = exports.withPinnedSearchPath = exports.schemaOfTable = exports.pinnedQuery = exports.PINNED_SEARCH_PATH = exports.STRATUM_CONTROL_ROLE = exports.STRATUM_TABLES = exports.migrateAllSchemas = exports.migrate = exports.Stratum = void 0;
4
+ exports.noopLogger = exports.defaultLogger = exports.MemoryRateLimitStore = exports.RateLimiter = exports.DecryptionError = exports.AbacPolicyLockedError = exports.InvalidAbacOperatorError = exports.AbacPolicyNotFoundError = exports.RegionNotFoundError = void 0;
4
5
  var stratum_js_1 = require("./stratum.js");
5
6
  Object.defineProperty(exports, "Stratum", { enumerable: true, get: function () { return stratum_js_1.Stratum; } });
6
7
  var migrate_js_1 = require("./migrate.js");
@@ -9,6 +10,20 @@ var migrate_schemas_js_1 = require("./migrate-schemas.js");
9
10
  Object.defineProperty(exports, "migrateAllSchemas", { enumerable: true, get: function () { return migrate_schemas_js_1.migrateAllSchemas; } });
10
11
  var stratum_tables_js_1 = require("./stratum-tables.js");
11
12
  Object.defineProperty(exports, "STRATUM_TABLES", { enumerable: true, get: function () { return stratum_tables_js_1.STRATUM_TABLES; } });
13
+ var migration_sql_js_1 = require("./migration-sql.js");
14
+ Object.defineProperty(exports, "STRATUM_CONTROL_ROLE", { enumerable: true, get: function () { return migration_sql_js_1.STRATUM_CONTROL_ROLE; } });
15
+ var pinned_query_js_1 = require("./pinned-query.js");
16
+ Object.defineProperty(exports, "PINNED_SEARCH_PATH", { enumerable: true, get: function () { return pinned_query_js_1.PINNED_SEARCH_PATH; } });
17
+ Object.defineProperty(exports, "pinnedQuery", { enumerable: true, get: function () { return pinned_query_js_1.pinnedQuery; } });
18
+ Object.defineProperty(exports, "schemaOfTable", { enumerable: true, get: function () { return pinned_query_js_1.schemaOfTable; } });
19
+ Object.defineProperty(exports, "withPinnedSearchPath", { enumerable: true, get: function () { return pinned_query_js_1.withPinnedSearchPath; } });
20
+ var stratum_policies_js_1 = require("./stratum-policies.js");
21
+ Object.defineProperty(exports, "stratumPolicyDrift", { enumerable: true, get: function () { return stratum_policies_js_1.stratumPolicyDrift; } });
22
+ Object.defineProperty(exports, "STRATUM_RLS_TABLES", { enumerable: true, get: function () { return stratum_policies_js_1.STRATUM_RLS_TABLES; } });
23
+ var role_model_js_1 = require("./role-model.js");
24
+ Object.defineProperty(exports, "bootstrapRolesSql", { enumerable: true, get: function () { return role_model_js_1.bootstrapRolesSql; } });
25
+ Object.defineProperty(exports, "inspectRoleModel", { enumerable: true, get: function () { return role_model_js_1.inspectRoleModel; } });
26
+ Object.defineProperty(exports, "APP_READ_TABLES", { enumerable: true, get: function () { return role_model_js_1.APP_READ_TABLES; } });
12
27
  var pool_helpers_js_1 = require("./pool-helpers.js");
13
28
  Object.defineProperty(exports, "withClient", { enumerable: true, get: function () { return pool_helpers_js_1.withClient; } });
14
29
  Object.defineProperty(exports, "withTransaction", { enumerable: true, get: function () { return pool_helpers_js_1.withTransaction; } });
@@ -57,6 +72,7 @@ Object.defineProperty(exports, "RegionNotFoundError", { enumerable: true, get: f
57
72
  Object.defineProperty(exports, "AbacPolicyNotFoundError", { enumerable: true, get: function () { return core_1.AbacPolicyNotFoundError; } });
58
73
  Object.defineProperty(exports, "InvalidAbacOperatorError", { enumerable: true, get: function () { return core_1.InvalidAbacOperatorError; } });
59
74
  Object.defineProperty(exports, "AbacPolicyLockedError", { enumerable: true, get: function () { return core_1.AbacPolicyLockedError; } });
75
+ Object.defineProperty(exports, "DecryptionError", { enumerable: true, get: function () { return core_1.DecryptionError; } });
60
76
  var rate_limit_service_js_1 = require("./services/rate-limit-service.js");
61
77
  Object.defineProperty(exports, "RateLimiter", { enumerable: true, get: function () { return rate_limit_service_js_1.RateLimiter; } });
62
78
  Object.defineProperty(exports, "MemoryRateLimitStore", { enumerable: true, get: function () { return rate_limit_service_js_1.MemoryRateLimitStore; } });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,2CAA4D;AAAnD,qGAAA,OAAO,OAAA;AAChB,2CAA4D;AAAnD,qGAAA,OAAO,OAAA;AAChB,2DAI8B;AAH5B,uHAAA,iBAAiB,OAAA;AAInB,yDAAqD;AAA5C,mHAAA,cAAc,OAAA;AACvB,qDAAgE;AAAvD,6GAAA,UAAU,OAAA;AAAE,kHAAA,eAAe,OAAA;AACpC,iDAIyB;AAHvB,6GAAA,YAAY,OAAA;AAId,+DAKgC;AAJ9B,8HAAA,sBAAsB,OAAA;AACtB,0HAAA,kBAAkB,OAAA;AAClB,yIAAA,iCAAiC,OAAA;AAGnC,+CAAqE;AAA5D,sGAAA,MAAM,OAAA;AAAE,yGAAA,SAAS,OAAA;AAAE,gHAAA,gBAAgB,OAAA;AAE5C,kFAAkF;AAClF,+EAA+E;AAC/E,8EAA8E;AAC9E,yCAgC0B;AA/BxB,iGAAA,SAAS,OAAA;AACT,oGAAA,YAAY,OAAA;AACZ,2GAAA,mBAAmB,OAAA;AACnB,gHAAA,wBAAwB,OAAA;AACxB,8GAAA,sBAAsB,OAAA;AACtB,gHAAA,wBAAwB,OAAA;AACxB,2GAAA,mBAAmB,OAAA;AACnB,4GAAA,oBAAoB,OAAA;AACpB,0GAAA,kBAAkB,OAAA;AAClB,+GAAA,uBAAuB,OAAA;AACvB,+GAAA,uBAAuB,OAAA;AACvB,kHAAA,0BAA0B,OAAA;AAC1B,+GAAA,uBAAuB,OAAA;AACvB,yHAAA,iCAAiC,OAAA;AACjC,6GAAA,qBAAqB,OAAA;AACrB,+GAAA,uBAAuB,OAAA;AACvB,uHAAA,+BAA+B,OAAA;AAC/B,yGAAA,iBAAiB,OAAA;AACjB,2GAAA,mBAAmB,OAAA;AACnB,uGAAA,eAAe,OAAA;AACf,yGAAA,iBAAiB,OAAA;AACjB,sGAAA,cAAc,OAAA;AACd,wGAAA,gBAAgB,OAAA;AAChB,4GAAA,oBAAoB,OAAA;AACpB,4GAAA,oBAAoB,OAAA;AACpB,4GAAA,oBAAoB,OAAA;AACpB,iHAAA,yBAAyB,OAAA;AACzB,2GAAA,mBAAmB,OAAA;AACnB,+GAAA,uBAAuB,OAAA;AACvB,gHAAA,wBAAwB,OAAA;AACxB,6GAAA,qBAAqB,OAAA;AAuBvB,0EAAqF;AAA5E,oHAAA,WAAW,OAAA;AAAE,6HAAA,oBAAoB,OAAA;AA2B1C,yCAAwD;AAA/C,0GAAA,aAAa,OAAA;AAAE,uGAAA,UAAU,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;AAAA,2CAA4D;AAAnD,qGAAA,OAAO,OAAA;AAChB,2CAA4D;AAAnD,qGAAA,OAAO,OAAA;AAChB,2DAI8B;AAH5B,uHAAA,iBAAiB,OAAA;AAInB,yDAAqD;AAA5C,mHAAA,cAAc,OAAA;AACvB,uDAA0D;AAAjD,wHAAA,oBAAoB,OAAA;AAC7B,qDAAyG;AAAhG,qHAAA,kBAAkB,OAAA;AAAE,8GAAA,WAAW,OAAA;AAAE,gHAAA,aAAa,OAAA;AAAE,uHAAA,oBAAoB,OAAA;AAC7E,6DAI+B;AAH7B,yHAAA,kBAAkB,OAAA;AAClB,yHAAA,kBAAkB,OAAA;AAGpB,iDAOyB;AANvB,kHAAA,iBAAiB,OAAA;AACjB,iHAAA,gBAAgB,OAAA;AAChB,gHAAA,eAAe,OAAA;AAKjB,qDAAgE;AAAvD,6GAAA,UAAU,OAAA;AAAE,kHAAA,eAAe,OAAA;AACpC,iDAIyB;AAHvB,6GAAA,YAAY,OAAA;AAId,+DAKgC;AAJ9B,8HAAA,sBAAsB,OAAA;AACtB,0HAAA,kBAAkB,OAAA;AAClB,yIAAA,iCAAiC,OAAA;AAGnC,+CAAqE;AAA5D,sGAAA,MAAM,OAAA;AAAE,yGAAA,SAAS,OAAA;AAAE,gHAAA,gBAAgB,OAAA;AAE5C,kFAAkF;AAClF,+EAA+E;AAC/E,8EAA8E;AAC9E,yCAiC0B;AAhCxB,iGAAA,SAAS,OAAA;AACT,oGAAA,YAAY,OAAA;AACZ,2GAAA,mBAAmB,OAAA;AACnB,gHAAA,wBAAwB,OAAA;AACxB,8GAAA,sBAAsB,OAAA;AACtB,gHAAA,wBAAwB,OAAA;AACxB,2GAAA,mBAAmB,OAAA;AACnB,4GAAA,oBAAoB,OAAA;AACpB,0GAAA,kBAAkB,OAAA;AAClB,+GAAA,uBAAuB,OAAA;AACvB,+GAAA,uBAAuB,OAAA;AACvB,kHAAA,0BAA0B,OAAA;AAC1B,+GAAA,uBAAuB,OAAA;AACvB,yHAAA,iCAAiC,OAAA;AACjC,6GAAA,qBAAqB,OAAA;AACrB,+GAAA,uBAAuB,OAAA;AACvB,uHAAA,+BAA+B,OAAA;AAC/B,yGAAA,iBAAiB,OAAA;AACjB,2GAAA,mBAAmB,OAAA;AACnB,uGAAA,eAAe,OAAA;AACf,yGAAA,iBAAiB,OAAA;AACjB,sGAAA,cAAc,OAAA;AACd,wGAAA,gBAAgB,OAAA;AAChB,4GAAA,oBAAoB,OAAA;AACpB,4GAAA,oBAAoB,OAAA;AACpB,4GAAA,oBAAoB,OAAA;AACpB,iHAAA,yBAAyB,OAAA;AACzB,2GAAA,mBAAmB,OAAA;AACnB,+GAAA,uBAAuB,OAAA;AACvB,gHAAA,wBAAwB,OAAA;AACxB,6GAAA,qBAAqB,OAAA;AACrB,uGAAA,eAAe,OAAA;AAwBjB,0EAAqF;AAA5E,oHAAA,WAAW,OAAA;AAAE,6HAAA,oBAAoB,OAAA;AAiC1C,yCAAwD;AAA/C,0GAAA,aAAa,OAAA;AAAE,uGAAA,UAAU,OAAA"}
@@ -4,6 +4,10 @@ export interface MigrateSchemasOptions {
4
4
  concurrency?: number;
5
5
  onProgress?: (schema: string, index: number, total: number) => void;
6
6
  enforceRls?: boolean;
7
+ /** The control role for migration 032; see MigrateOptions.controlRole. */
8
+ controlRole?: string;
9
+ /** Lets migration 032 grant the control role to the login of `pool`; see MigrateOptions.applyControlRole. */
10
+ applyControlRole?: boolean;
7
11
  }
8
12
  export interface MigrateSchemasResult {
9
13
  succeeded: string[];
@@ -1 +1 @@
1
- {"version":3,"file":"migrate-schemas.d.ts","sourceRoot":"","sources":["../src/migrate-schemas.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,IAAI,CAAC;AAGpB,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACpE,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,EAAE,CAAC;CAC5C;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CA8D/B"}
1
+ {"version":3,"file":"migrate-schemas.d.ts","sourceRoot":"","sources":["../src/migrate-schemas.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,IAAI,CAAC;AAKpB,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACpE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6GAA6G;IAC7G,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,EAAE,CAAC;CAC5C;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CAoE/B"}
@@ -7,6 +7,8 @@ exports.migrateAllSchemas = migrateAllSchemas;
7
7
  const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
9
  const pool_helpers_js_1 = require("./pool-helpers.js");
10
+ const migration_sql_js_1 = require("./migration-sql.js");
11
+ const migrate_js_1 = require("./migrate.js");
10
12
  /**
11
13
  * Discover all tenant schemas (tenants with SCHEMA_PER_TENANT isolation)
12
14
  * and run the standard migration set against each one.
@@ -14,7 +16,12 @@ const pool_helpers_js_1 = require("./pool-helpers.js");
14
16
  * Continues on error: schemas that fail are collected in result.failed[].
15
17
  */
16
18
  async function migrateAllSchemas(options) {
17
- const { pool, concurrency = 5, onProgress, enforceRls } = options;
19
+ const { pool, concurrency = 5, onProgress, enforceRls, controlRole, applyControlRole } = options;
20
+ if (controlRole !== undefined)
21
+ (0, migration_sql_js_1.assertRoleName)(controlRole, "control role");
22
+ if (enforceRls) {
23
+ await (0, migrate_js_1.assertRoleSubjectToRls)(pool);
24
+ }
18
25
  // Discover tenant schemas. The tenants registry is under FORCE RLS, so
19
26
  // discovery runs under the control-plane bypass like every other lib read.
20
27
  const { rows } = await (0, pool_helpers_js_1.withClient)(pool, (client) => client.query(`SELECT slug FROM tenants WHERE isolation_strategy = 'SCHEMA_PER_TENANT' AND (deleted_at IS NULL) ORDER BY slug`));
@@ -32,15 +39,16 @@ async function migrateAllSchemas(options) {
32
39
  .readdirSync(migrationsDir)
33
40
  .filter((f) => f.endsWith(".sql"))
34
41
  .sort();
35
- const migrationSql = files.map((file) => ({
42
+ const superuser = await (0, migration_sql_js_1.isSuperuser)(pool);
43
+ const migrations = files.map((file) => ({
36
44
  name: file,
37
- sql: node_fs_1.default.readFileSync(node_path_1.default.join(migrationsDir, file), "utf-8"),
45
+ sql: (0, migration_sql_js_1.migrationSql)(file, node_fs_1.default.readFileSync(node_path_1.default.join(migrationsDir, file), "utf-8"), superuser),
38
46
  }));
39
47
  // Process schemas in chunks of `concurrency` size
40
48
  let completed = 0;
41
49
  for (let i = 0; i < schemas.length; i += concurrency) {
42
50
  const chunk = schemas.slice(i, i + concurrency);
43
- const results = await Promise.allSettled(chunk.map((schema) => migrateSchema(pool, schema, migrationSql, enforceRls)));
51
+ const results = await Promise.allSettled(chunk.map((schema) => migrateSchema(pool, schema, migrations, enforceRls, controlRole, applyControlRole)));
44
52
  for (let j = 0; j < results.length; j++) {
45
53
  const schema = chunk[j];
46
54
  const outcome = results[j];
@@ -60,7 +68,7 @@ async function migrateAllSchemas(options) {
60
68
  }
61
69
  return result;
62
70
  }
63
- async function migrateSchema(pool, schema, migrations, enforceRls) {
71
+ async function migrateSchema(pool, schema, migrations, enforceRls, controlRole, applyControlRole) {
64
72
  // Use a hash of the schema name for a unique advisory lock key per schema
65
73
  const lockKey = hashSchemaLock(schema);
66
74
  const quoted = quoteIdent(schema);
@@ -69,7 +77,7 @@ async function migrateSchema(pool, schema, migrations, enforceRls) {
69
77
  try {
70
78
  await client.query("BEGIN");
71
79
  // Advisory lock scoped to this schema
72
- await client.query(`SELECT pg_advisory_xact_lock($1)`, [lockKey]);
80
+ await client.query(`SELECT pg_catalog.pg_advisory_xact_lock($1::pg_catalog.int8)`, [lockKey]);
73
81
  // Set search_path to the tenant schema. public stays on the path because
74
82
  // the migration SQL uses extension types and functions installed there
75
83
  // (ltree, uuid_generate_v4).
@@ -93,6 +101,8 @@ async function migrateSchema(pool, schema, migrations, enforceRls) {
93
101
  if (enforceRls) {
94
102
  await client.query("SET LOCAL stratum.enforce_rls = 'on'");
95
103
  }
104
+ await (0, migration_sql_js_1.setControlRole)(client, controlRole);
105
+ await (0, migration_sql_js_1.setApplyControlRole)(client, applyControlRole);
96
106
  await client.query(migration.sql);
97
107
  await client.query(`INSERT INTO ${quoted}._migrations (name) VALUES ($1)`, [
98
108
  migration.name,
@@ -1 +1 @@
1
- {"version":3,"file":"migrate-schemas.js","sourceRoot":"","sources":["../src/migrate-schemas.ts"],"names":[],"mappings":";;;;;AAuBA,8CAgEC;AAvFD,sDAAyB;AACzB,0DAA6B;AAE7B,uDAA+C;AAc/C;;;;;GAKG;AACI,KAAK,UAAU,iBAAiB,CACrC,OAA8B;IAE9B,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;IAElE,uEAAuE;IACvE,2EAA2E;IAC3E,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAA,4BAAU,EAAC,IAAI,EAAE,CAAC,MAAM,EAAE,EAAE,CACjD,MAAM,CAAC,KAAK,CACV,gHAAgH,CACjH,CACF,CAAC;IAEF,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACpD,MAAM,MAAM,GAAyB,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IAEnE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,4BAA4B;IAC5B,MAAM,aAAa,GAAG,mBAAI,CAAC,OAAO,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IAC5D,IAAI,CAAC,iBAAE,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CACb,gCAAgC,aAAa,sDAAsD,CACpG,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,iBAAE;SACb,WAAW,CAAC,aAAa,CAAC;SAC1B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;SACjC,IAAI,EAAE,CAAC;IAEV,MAAM,YAAY,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACxC,IAAI,EAAE,IAAI;QACV,GAAG,EAAE,iBAAE,CAAC,YAAY,CAAC,mBAAI,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC;KAC9D,CAAC,CAAC,CAAC;IAEJ,kDAAkD;IAClD,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,WAAW,EAAE,CAAC;QACrD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CACtC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC,CAC7E,CAAC;QAEF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACxC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACxB,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;YAC3B,IAAI,OAAO,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;gBACnC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAChC,CAAC;iBAAM,CAAC;gBACN,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC;gBAC3B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;oBACjB,MAAM;oBACN,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;iBAC3D,CAAC,CAAC;YACL,CAAC;YACD,SAAS,EAAE,CAAC;YACZ,UAAU,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,KAAK,UAAU,aAAa,CAC1B,IAAa,EACb,MAAc,EACd,UAA2C,EAC3C,UAAoB;IAEpB,0EAA0E;IAC1E,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAElC,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QACpC,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAE5B,sCAAsC;YACtC,MAAM,MAAM,CAAC,KAAK,CAAC,kCAAkC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;YAElE,yEAAyE;YACzE,uEAAuE;YACvE,6BAA6B;YAC7B,MAAM,MAAM,CAAC,KAAK,CAAC,2BAA2B,MAAM,UAAU,CAAC,CAAC;YAEhE,0EAA0E;YAC1E,qEAAqE;YACrE,yEAAyE;YACzE,MAAM,MAAM,CAAC,KAAK,CAAC;qCACY,MAAM;;;;;OAKpC,CAAC,CAAC;YAEH,2BAA2B;YAC3B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,KAAK,CACjC,iBAAiB,MAAM,8BAA8B,EACrD,CAAC,SAAS,CAAC,IAAI,CAAC,CACjB,CAAC;YACF,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpB,MAAM,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;gBAC7B,SAAS;YACX,CAAC;YAED,IAAI,UAAU,EAAE,CAAC;gBACf,MAAM,MAAM,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;YAC7D,CAAC;YAED,MAAM,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YAClC,MAAM,MAAM,CAAC,KAAK,CAAC,eAAe,MAAM,iCAAiC,EAAE;gBACzE,SAAS,CAAC,IAAI;aACf,CAAC,CAAC;YACH,MAAM,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC/B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YACjC,CAAC;YAAC,MAAM,CAAC;gBACP,6BAA6B;YAC/B,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;gBAAS,CAAC;YACT,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,cAAc,CAAC,MAAc;IACpC,IAAI,IAAI,GAAG,IAAI,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACzD,CAAC;IACD,iEAAiE;IACjE,OAAO,CAAC,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,kBAAkB;AACpD,CAAC;AAED,SAAS,UAAU,CAAC,IAAY;IAC9B,oEAAoE;IACpE,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,EAAE,CAAC,CAAC;IAClD,CAAC;IACD,4EAA4E;IAC5E,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,iCAAiC,IAAI,EAAE,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,IAAI,IAAI,GAAG,CAAC;AACrB,CAAC"}
1
+ {"version":3,"file":"migrate-schemas.js","sourceRoot":"","sources":["../src/migrate-schemas.ts"],"names":[],"mappings":"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"}
package/dist/migrate.d.ts CHANGED
@@ -3,6 +3,30 @@ export interface MigrateOptions {
3
3
  pool: pg.Pool;
4
4
  /** When true, SET stratum.enforce_rls = 'on' before running migrations (hard-fail on BYPASSRLS). */
5
5
  enforceRls?: boolean;
6
+ /**
7
+ * The name of the NOLOGIN control role that migration 032 creates and names
8
+ * in its policies. Default: the stratum.control_role setting of the session
9
+ * (for example from ALTER DATABASE ... SET), then the role the database
10
+ * already uses, then `stratum_control`. Roles are cluster-wide, so set it
11
+ * when several databases on one server need separate control roles.
12
+ */
13
+ controlRole?: string;
14
+ /**
15
+ * Lets migration 032 create the control role and grant it to the login of
16
+ * `pool`, then apply it. Set it only when `pool` is the library's admin
17
+ * login (the login behind adminPool), never the application's: a member
18
+ * of the control role passes every Stratum policy. Stratum's autoMigrate
19
+ * sets it when it runs on adminPool. Without it, 032 applies the control
20
+ * role only when that grants nothing new (a superuser, or a login that is
21
+ * already a member), and otherwise warns with the SQL to run.
22
+ */
23
+ applyControlRole?: boolean;
6
24
  }
25
+ /**
26
+ * Throws when the connecting role has BYPASSRLS, so row-level security would
27
+ * not apply to it. Used by every enforceRls entry point, so the check does not
28
+ * depend on migration 001 running.
29
+ */
30
+ export declare function assertRoleSubjectToRls(pool: pg.Pool): Promise<void>;
7
31
  export declare function migrate(options: MigrateOptions): Promise<void>;
8
32
  //# sourceMappingURL=migrate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC;IACd,oGAAoG;IACpG,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,wBAAsB,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CA2DpE"}
1
+ {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,IAAI,CAAC;AAIpB,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC;IACd,oGAAoG;IACpG,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;;OAQG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAUzE;AAED,wBAAsB,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAoFpE"}
package/dist/migrate.js CHANGED
@@ -3,14 +3,42 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.assertRoleSubjectToRls = assertRoleSubjectToRls;
6
7
  exports.migrate = migrate;
7
8
  const node_fs_1 = __importDefault(require("node:fs"));
8
9
  const node_path_1 = __importDefault(require("node:path"));
10
+ const migration_sql_js_1 = require("./migration-sql.js");
11
+ const pinned_query_js_1 = require("./pinned-query.js");
12
+ /**
13
+ * Throws when the connecting role has BYPASSRLS, so row-level security would
14
+ * not apply to it. Used by every enforceRls entry point, so the check does not
15
+ * depend on migration 001 running.
16
+ */
17
+ async function assertRoleSubjectToRls(pool) {
18
+ const { rows } = await pool.query("SELECT current_user AS role, rolbypassrls AS bypass FROM pg_catalog.pg_roles WHERE rolname = current_user");
19
+ if (rows[0]?.bypass) {
20
+ throw new Error(`SECURITY: Application role "${rows[0].role}" has BYPASSRLS privilege. ` +
21
+ "Connect as a dedicated role without BYPASSRLS, or turn enforceRls off for development.");
22
+ }
23
+ }
9
24
  async function migrate(options) {
10
- const { pool, enforceRls } = options;
25
+ const { pool, enforceRls, controlRole, applyControlRole } = options;
26
+ if (controlRole !== undefined)
27
+ (0, migration_sql_js_1.assertRoleName)(controlRole, "control role");
28
+ if (enforceRls) {
29
+ await assertRoleSubjectToRls(pool);
30
+ }
31
+ // The migrations create their objects in the first schema of the search
32
+ // path; the tracking table lives there too, named with that schema.
33
+ const current = await pool.query("SELECT pg_catalog.current_schema() AS schema");
34
+ const schema = current.rows[0]?.schema;
35
+ if (!schema) {
36
+ throw new Error("[stratum] migrate: no schema on the search path of the migrating login to create the Stratum tables in");
37
+ }
38
+ const migrationsTable = `${(0, pinned_query_js_1.quoteIdentifier)(schema)}._migrations`;
11
39
  // Create migrations tracking table
12
40
  await pool.query(`
13
- CREATE TABLE IF NOT EXISTS _migrations (
41
+ CREATE TABLE IF NOT EXISTS ${migrationsTable} (
14
42
  id SERIAL PRIMARY KEY,
15
43
  name TEXT NOT NULL UNIQUE,
16
44
  applied_at TIMESTAMPTZ NOT NULL DEFAULT now()
@@ -25,14 +53,22 @@ async function migrate(options) {
25
53
  .readdirSync(migrationsDir)
26
54
  .filter((f) => f.endsWith(".sql"))
27
55
  .sort();
56
+ // Migrations 029 and 031 created helper functions with `SET app.*` clauses,
57
+ // which PostgreSQL accepts only from a superuser (or a role granted SET on
58
+ // the parameter). For any other migrating role, migrationSql() drops those
59
+ // clause lines from these two files only; migration 032 then re-creates
60
+ // both functions without them when it applies the control role. Until it
61
+ // does, they see only what their caller sees, which can only narrow what
62
+ // they return. See migration-sql.ts.
63
+ const superuser = await (0, migration_sql_js_1.isSuperuser)(pool);
28
64
  for (const file of files) {
29
65
  const client = await pool.connect();
30
66
  try {
31
67
  await client.query("BEGIN");
32
68
  // Acquire advisory lock to prevent concurrent migrations
33
- await client.query("SELECT pg_advisory_xact_lock(8675309)");
69
+ await client.query("SELECT pg_catalog.pg_advisory_xact_lock(8675309::pg_catalog.int8)");
34
70
  // Re-check if already applied (after lock, to prevent TOCTOU race)
35
- const { rows } = await client.query("SELECT 1 FROM _migrations WHERE name = $1", [file]);
71
+ const { rows } = await client.query(`SELECT 1 FROM ${migrationsTable} WHERE name = $1`, [file]);
36
72
  if (rows.length > 0) {
37
73
  await client.query("COMMIT");
38
74
  continue;
@@ -41,9 +77,11 @@ async function migrate(options) {
41
77
  if (enforceRls) {
42
78
  await client.query("SET LOCAL stratum.enforce_rls = 'on'");
43
79
  }
44
- const sql = node_fs_1.default.readFileSync(node_path_1.default.join(migrationsDir, file), "utf-8");
80
+ await (0, migration_sql_js_1.setControlRole)(client, controlRole);
81
+ await (0, migration_sql_js_1.setApplyControlRole)(client, applyControlRole);
82
+ const sql = (0, migration_sql_js_1.migrationSql)(file, node_fs_1.default.readFileSync(node_path_1.default.join(migrationsDir, file), "utf-8"), superuser);
45
83
  await client.query(sql);
46
- await client.query("INSERT INTO _migrations (name) VALUES ($1)", [file]);
84
+ await client.query(`INSERT INTO ${migrationsTable} (name) VALUES ($1)`, [file]);
47
85
  await client.query("COMMIT");
48
86
  }
49
87
  catch (err) {
@@ -1 +1 @@
1
- {"version":3,"file":"migrate.js","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":";;;;;AAUA,0BA2DC;AArED,sDAAyB;AACzB,0DAA6B;AAStB,KAAK,UAAU,OAAO,CAAC,OAAuB;IACnD,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;IAErC,mCAAmC;IACnC,MAAM,IAAI,CAAC,KAAK,CAAC;;;;;;GAMhB,CAAC,CAAC;IAEH,sBAAsB;IACtB,MAAM,aAAa,GAAG,mBAAI,CAAC,OAAO,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IAC5D,IAAI,CAAC,iBAAE,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CACb,gCAAgC,aAAa,sDAAsD,CACpG,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,iBAAE;SACb,WAAW,CAAC,aAAa,CAAC;SAC1B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;SACjC,IAAI,EAAE,CAAC;IAEV,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QACpC,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAE5B,yDAAyD;YACzD,MAAM,MAAM,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;YAE5D,mEAAmE;YACnE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,KAAK,CACjC,2CAA2C,EAC3C,CAAC,IAAI,CAAC,CACP,CAAC;YACF,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpB,MAAM,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;gBAC7B,SAAS;YACX,CAAC;YAED,wCAAwC;YACxC,IAAI,UAAU,EAAE,CAAC;gBACf,MAAM,MAAM,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;YAC7D,CAAC;YAED,MAAM,GAAG,GAAG,iBAAE,CAAC,YAAY,CAAC,mBAAI,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;YACrE,MAAM,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACxB,MAAM,MAAM,CAAC,KAAK,CAAC,4CAA4C,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;YACzE,MAAM,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC/B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC;gBAAC,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,6BAA6B,CAAC,CAAC;YAC/E,MAAM,GAAG,CAAC;QACZ,CAAC;gBAAS,CAAC;YACT,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,CAAC;IACH,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"migrate.js","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import type pg from "pg";
2
+ /** The default name of the NOLOGIN control role (migration 032). */
3
+ export declare const STRATUM_CONTROL_ROLE = "stratum_control";
4
+ /** A role name Stratum accepts: a plain lowercase identifier. */
5
+ export declare const ROLE_NAME: RegExp;
6
+ /** Throws when `role` is not a plain lowercase identifier. */
7
+ export declare function assertRoleName(role: string, what: string): void;
8
+ /** The SQL to run for one migration file. */
9
+ export declare function migrationSql(name: string, sql: string, superuser: boolean): string;
10
+ /** Whether the role of `client` is a superuser. */
11
+ export declare function isSuperuser(client: pg.PoolClient | pg.Pool): Promise<boolean>;
12
+ /**
13
+ * Sets stratum.control_role for the current transaction, which migration 032
14
+ * reads. Without a name the setting stays as the session has it.
15
+ */
16
+ export declare function setControlRole(client: pg.PoolClient, controlRole: string | undefined): Promise<void>;
17
+ /**
18
+ * Sets stratum.apply_control_role = 'on' for the current transaction when
19
+ * `apply` is true. Migration 032 grants the control role to the migrating
20
+ * login only with this opt-in (or when the login is a superuser or already a
21
+ * member), because that login must be the library's admin login and never
22
+ * the application's.
23
+ */
24
+ export declare function setApplyControlRole(client: pg.PoolClient, apply: boolean | undefined): Promise<void>;
25
+ //# sourceMappingURL=migration-sql.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration-sql.d.ts","sourceRoot":"","sources":["../src/migration-sql.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAEzB,oEAAoE;AACpE,eAAO,MAAM,oBAAoB,oBAAoB,CAAC;AAEtD,iEAAiE;AACjE,eAAO,MAAM,SAAS,QAA4B,CAAC;AAEnD,8DAA8D;AAC9D,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAI/D;AAgBD,6CAA6C;AAC7C,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,MAAM,CAGlF;AAED,mDAAmD;AACnD,wBAAsB,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,GAAG,EAAE,CAAC,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAKnF;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,EAAE,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAG1G;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,EAAE,KAAK,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAG1G"}