@empire-builder-kit/nx 1.0.0-beta.4

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 (185) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +5 -0
  3. package/README.md +25 -0
  4. package/executors.json +54 -0
  5. package/generators.json +35 -0
  6. package/migrations/standard-pre-v1-to-v1.md +11 -0
  7. package/package.json +66 -0
  8. package/src/blueprints/execution.d.ts +31 -0
  9. package/src/blueprints/execution.js +166 -0
  10. package/src/blueprints/execution.js.map +1 -0
  11. package/src/blueprints/index.d.ts +5 -0
  12. package/src/blueprints/index.js +9 -0
  13. package/src/blueprints/index.js.map +1 -0
  14. package/src/blueprints/inputs.d.ts +43 -0
  15. package/src/blueprints/inputs.js +103 -0
  16. package/src/blueprints/inputs.js.map +1 -0
  17. package/src/blueprints/manifest.d.ts +241 -0
  18. package/src/blueprints/manifest.js +369 -0
  19. package/src/blueprints/manifest.js.map +1 -0
  20. package/src/blueprints/resolver.d.ts +28 -0
  21. package/src/blueprints/resolver.js +214 -0
  22. package/src/blueprints/resolver.js.map +1 -0
  23. package/src/blueprints/transitions.d.ts +20 -0
  24. package/src/blueprints/transitions.js +61 -0
  25. package/src/blueprints/transitions.js.map +1 -0
  26. package/src/executors/deploy/deploy.d.ts +4 -0
  27. package/src/executors/deploy/deploy.js +6 -0
  28. package/src/executors/deploy/deploy.js.map +1 -0
  29. package/src/executors/dev/dev.d.ts +4 -0
  30. package/src/executors/dev/dev.js +6 -0
  31. package/src/executors/dev/dev.js.map +1 -0
  32. package/src/executors/dev-doctor/dev-doctor.d.ts +18 -0
  33. package/src/executors/dev-doctor/dev-doctor.js +145 -0
  34. package/src/executors/dev-doctor/dev-doctor.js.map +1 -0
  35. package/src/executors/dev-doctor/schema.json +17 -0
  36. package/src/executors/dev-setup/dev-setup.d.ts +11 -0
  37. package/src/executors/dev-setup/dev-setup.js +454 -0
  38. package/src/executors/dev-setup/dev-setup.js.map +1 -0
  39. package/src/executors/dev-setup/schema.json +16 -0
  40. package/src/executors/fleet/fleet.d.ts +51 -0
  41. package/src/executors/fleet/fleet.js +529 -0
  42. package/src/executors/fleet/fleet.js.map +1 -0
  43. package/src/executors/fleet/schema.json +25 -0
  44. package/src/executors/foundation-preflight/foundation-preflight.d.ts +15 -0
  45. package/src/executors/foundation-preflight/foundation-preflight.js +94 -0
  46. package/src/executors/foundation-preflight/foundation-preflight.js.map +1 -0
  47. package/src/executors/foundation-preflight/schema.json +31 -0
  48. package/src/executors/foundation-remove-preflight/foundation-remove-preflight.d.ts +13 -0
  49. package/src/executors/foundation-remove-preflight/foundation-remove-preflight.js +69 -0
  50. package/src/executors/foundation-remove-preflight/foundation-remove-preflight.js.map +1 -0
  51. package/src/executors/foundation-remove-preflight/schema.json +17 -0
  52. package/src/executors/refresh/refresh.d.ts +4 -0
  53. package/src/executors/refresh/refresh.js +6 -0
  54. package/src/executors/refresh/refresh.js.map +1 -0
  55. package/src/executors/remove/remove.d.ts +4 -0
  56. package/src/executors/remove/remove.js +6 -0
  57. package/src/executors/remove/remove.js.map +1 -0
  58. package/src/executors/sst-lifecycle/run-sst-command.d.ts +28 -0
  59. package/src/executors/sst-lifecycle/run-sst-command.js +154 -0
  60. package/src/executors/sst-lifecycle/run-sst-command.js.map +1 -0
  61. package/src/executors/sst-lifecycle/schema.json +45 -0
  62. package/src/executors/unlock/unlock.d.ts +4 -0
  63. package/src/executors/unlock/unlock.js +6 -0
  64. package/src/executors/unlock/unlock.js.map +1 -0
  65. package/src/foundation/aurora-logical-database.d.ts +76 -0
  66. package/src/foundation/aurora-logical-database.js +419 -0
  67. package/src/foundation/aurora-logical-database.js.map +1 -0
  68. package/src/foundation/discovery.d.ts +55 -0
  69. package/src/foundation/discovery.js +55 -0
  70. package/src/foundation/discovery.js.map +1 -0
  71. package/src/foundation/index.d.ts +6 -0
  72. package/src/foundation/index.js +10 -0
  73. package/src/foundation/index.js.map +1 -0
  74. package/src/foundation/local-database-contract.d.ts +30 -0
  75. package/src/foundation/local-database-contract.js +75 -0
  76. package/src/foundation/local-database-contract.js.map +1 -0
  77. package/src/foundation/preflight.d.ts +31 -0
  78. package/src/foundation/preflight.js +114 -0
  79. package/src/foundation/preflight.js.map +1 -0
  80. package/src/foundation/provision-database-bindings.d.ts +30 -0
  81. package/src/foundation/provision-database-bindings.js +113 -0
  82. package/src/foundation/provision-database-bindings.js.map +1 -0
  83. package/src/foundation/provision-logical-database.d.ts +26 -0
  84. package/src/foundation/provision-logical-database.js +162 -0
  85. package/src/foundation/provision-logical-database.js.map +1 -0
  86. package/src/foundation/requirements.d.ts +37 -0
  87. package/src/foundation/requirements.js +141 -0
  88. package/src/foundation/requirements.js.map +1 -0
  89. package/src/foundation/stages.d.ts +14 -0
  90. package/src/foundation/stages.js +51 -0
  91. package/src/foundation/stages.js.map +1 -0
  92. package/src/generators/function/function.d.ts +13 -0
  93. package/src/generators/function/function.js +71 -0
  94. package/src/generators/function/function.js.map +1 -0
  95. package/src/generators/function/schema.d.ts +5 -0
  96. package/src/generators/function/schema.json +20 -0
  97. package/src/generators/job/job.d.ts +4 -0
  98. package/src/generators/job/job.js +5 -0
  99. package/src/generators/job/job.js.map +1 -0
  100. package/src/generators/preset/generator.d.ts +5 -0
  101. package/src/generators/preset/generator.js +41 -0
  102. package/src/generators/preset/generator.js.map +1 -0
  103. package/src/generators/preset/schema.d.ts +4 -0
  104. package/src/generators/preset/schema.json +22 -0
  105. package/src/generators/preset/workspace-files.d.ts +18 -0
  106. package/src/generators/preset/workspace-files.js +895 -0
  107. package/src/generators/preset/workspace-files.js.map +1 -0
  108. package/src/generators/service/service.d.ts +4 -0
  109. package/src/generators/service/service.js +5 -0
  110. package/src/generators/service/service.js.map +1 -0
  111. package/src/generators/slice/schema.d.ts +7 -0
  112. package/src/generators/slice/schema.json +38 -0
  113. package/src/generators/slice/slice.d.ts +26 -0
  114. package/src/generators/slice/slice.js +1676 -0
  115. package/src/generators/slice/slice.js.map +1 -0
  116. package/src/generators/upgrade/schema.d.ts +8 -0
  117. package/src/generators/upgrade/schema.json +31 -0
  118. package/src/generators/upgrade/upgrade.d.ts +27 -0
  119. package/src/generators/upgrade/upgrade.js +666 -0
  120. package/src/generators/upgrade/upgrade.js.map +1 -0
  121. package/src/generators/workload/schema.d.ts +6 -0
  122. package/src/generators/workload/schema.json +21 -0
  123. package/src/generators/workload/workload.d.ts +16 -0
  124. package/src/generators/workload/workload.js +157 -0
  125. package/src/generators/workload/workload.js.map +1 -0
  126. package/src/index.d.ts +5 -0
  127. package/src/index.js +9 -0
  128. package/src/index.js.map +1 -0
  129. package/src/local-dev/contracts.d.ts +31 -0
  130. package/src/local-dev/contracts.js +126 -0
  131. package/src/local-dev/contracts.js.map +1 -0
  132. package/src/local-dev/gateway-daemon.d.ts +4 -0
  133. package/src/local-dev/gateway-daemon.js +39 -0
  134. package/src/local-dev/gateway-daemon.js.map +1 -0
  135. package/src/local-dev/gateway.d.ts +60 -0
  136. package/src/local-dev/gateway.js +368 -0
  137. package/src/local-dev/gateway.js.map +1 -0
  138. package/src/local-dev/identity.d.ts +16 -0
  139. package/src/local-dev/identity.js +101 -0
  140. package/src/local-dev/identity.js.map +1 -0
  141. package/src/local-dev/index.d.ts +7 -0
  142. package/src/local-dev/index.js +11 -0
  143. package/src/local-dev/index.js.map +1 -0
  144. package/src/local-dev/portless.d.ts +15 -0
  145. package/src/local-dev/portless.js +115 -0
  146. package/src/local-dev/portless.js.map +1 -0
  147. package/src/local-dev/ports.d.ts +10 -0
  148. package/src/local-dev/ports.js +39 -0
  149. package/src/local-dev/ports.js.map +1 -0
  150. package/src/local-dev/proxy.d.ts +37 -0
  151. package/src/local-dev/proxy.js +271 -0
  152. package/src/local-dev/proxy.js.map +1 -0
  153. package/src/local-dev/tls.d.ts +24 -0
  154. package/src/local-dev/tls.js +294 -0
  155. package/src/local-dev/tls.js.map +1 -0
  156. package/src/ownership/composition.d.ts +16 -0
  157. package/src/ownership/composition.js +125 -0
  158. package/src/ownership/composition.js.map +1 -0
  159. package/src/ownership/foundation-record.d.ts +66 -0
  160. package/src/ownership/foundation-record.js +108 -0
  161. package/src/ownership/foundation-record.js.map +1 -0
  162. package/src/ownership/hash.d.ts +2 -0
  163. package/src/ownership/hash.js +10 -0
  164. package/src/ownership/hash.js.map +1 -0
  165. package/src/ownership/index.d.ts +6 -0
  166. package/src/ownership/index.js +10 -0
  167. package/src/ownership/index.js.map +1 -0
  168. package/src/ownership/json-ownership.d.ts +13 -0
  169. package/src/ownership/json-ownership.js +147 -0
  170. package/src/ownership/json-ownership.js.map +1 -0
  171. package/src/ownership/record.d.ts +186 -0
  172. package/src/ownership/record.js +336 -0
  173. package/src/ownership/record.js.map +1 -0
  174. package/src/ownership/workspace-record.d.ts +66 -0
  175. package/src/ownership/workspace-record.js +108 -0
  176. package/src/ownership/workspace-record.js.map +1 -0
  177. package/src/schemas/blueprint-input-schema-v1.json +23 -0
  178. package/src/schemas/blueprint-v1.json +170 -0
  179. package/src/schemas/foundation-ownership-v2.json +42 -0
  180. package/src/schemas/foundation-requirement-v1.json +32 -0
  181. package/src/schemas/generated-ownership-v2.json +117 -0
  182. package/src/schemas/workspace-ownership-v2.json +42 -0
  183. package/src/validation.d.ts +14 -0
  184. package/src/validation.js +14 -0
  185. package/src/validation.js.map +1 -0
@@ -0,0 +1,419 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AuroraLogicalDbProvider = exports.RdsDataApiExecutor = void 0;
4
+ exports.createDatabaseSql = createDatabaseSql;
5
+ exports.databaseExistsSql = databaseExistsSql;
6
+ exports.roleExistsSql = roleExistsSql;
7
+ exports.createRoleSql = createRoleSql;
8
+ exports.alterRolePasswordSql = alterRolePasswordSql;
9
+ exports.grantScopedAccessSql = grantScopedAccessSql;
10
+ exports.createAuroraLogicalDbResource = createAuroraLogicalDbResource;
11
+ const node_crypto_1 = require("node:crypto");
12
+ const GENERATED_PASSWORD_SECRET_OUTPUTS = [
13
+ 'readwritePassword',
14
+ 'readonlyPassword',
15
+ ];
16
+ const SQL_PASSWORD_LITERAL_PATTERN = /\b(PASSWORD\s+')((?:''|[^'])*)(')/gi;
17
+ function redactSqlPasswordLiterals(message) {
18
+ return message.replace(SQL_PASSWORD_LITERAL_PATTERN, '$1[REDACTED]$3');
19
+ }
20
+ // Value-based redaction guard. Secrets shorter than this are NOT replaced by
21
+ // value — a tiny value (e.g. a 3-char test password) is likely to appear as
22
+ // an incidental substring of unrelated identifiers or SQL keywords and
23
+ // global replacement would mangle the message. Short values embedded in a
24
+ // well-formed `PASSWORD '...'` literal are still caught by the pattern pass.
25
+ // The default generator always emits 32 chars, so real deployments never hit
26
+ // this guard.
27
+ const MIN_REDACTABLE_SECRET_LENGTH = 6;
28
+ // Expands each in-scope secret into the textual variants that can appear in
29
+ // a Data API error: the raw value and its single-quote-escaped form (the SQL
30
+ // generators double `'` before embedding, so a Postgres echo of the
31
+ // statement text contains the ESCAPED variant). Longest-first ordering makes
32
+ // sure an escaped variant that contains the raw value as a substring is
33
+ // replaced before the raw pass can split it in half.
34
+ function secretVariants(secrets) {
35
+ const variants = new Set();
36
+ for (const secret of secrets) {
37
+ if (!secret || secret.length < MIN_REDACTABLE_SECRET_LENGTH)
38
+ continue;
39
+ variants.add(secret);
40
+ const escaped = secret.replace(/'/g, "''");
41
+ if (escaped !== secret) {
42
+ variants.add(escaped);
43
+ }
44
+ }
45
+ return [...variants].sort((a, b) => b.length - a.length);
46
+ }
47
+ function redactSecretValues(text, variants) {
48
+ let result = text;
49
+ for (const variant of variants) {
50
+ // split/join instead of a RegExp so secret contents never need escaping.
51
+ result = result.split(variant).join('[REDACTED]');
52
+ }
53
+ return result;
54
+ }
55
+ // Redacts secrets from an unknown thrown value and re-wraps it as a plain
56
+ // Error carrying only `name`/`message`/`stack`. Everything else (`cause`,
57
+ // enumerable props, AWS SDK payloads) is intentionally dropped — those
58
+ // channels could carry unredacted copies of the statement.
59
+ //
60
+ // Two passes, defense in depth:
61
+ // 1. VALUE-based: replaces every occurrence of the in-scope secret values
62
+ // (raw + quote-escaped variants) regardless of surrounding format —
63
+ // covers truncated `PASSWORD 'abc` fragments with no closing quote,
64
+ // Postgres `at or near "..."` echoes, and any future drift in the
65
+ // statement shape.
66
+ // 2. PATTERN-based: the well-formed `PASSWORD '...'` regex — covers values
67
+ // NOT in scope (e.g. a stale password echoed from a previous deploy's
68
+ // failed statement).
69
+ function redactDataApiError(error, secrets = []) {
70
+ const variants = secretVariants(secrets);
71
+ const redact = (text) => redactSqlPasswordLiterals(redactSecretValues(text, variants));
72
+ let message = redact(error instanceof Error ? error.message : String(error));
73
+ // Keep Data API failures debuggable: surface the (non-secret) AWS SDK
74
+ // request id, since the wrapper drops `$metadata` along with everything
75
+ // else on the original error.
76
+ const requestId = error
77
+ ?.$metadata?.requestId;
78
+ if (typeof requestId === 'string' && requestId.length > 0) {
79
+ message += ` (Data API requestId: ${requestId})`;
80
+ }
81
+ const redacted = new Error(message);
82
+ if (error instanceof Error) {
83
+ redacted.name = error.name;
84
+ if (error.stack) {
85
+ redacted.stack = redact(error.stack);
86
+ }
87
+ }
88
+ return redacted;
89
+ }
90
+ // Aurora Serverless v2 clusters configured with `min: 0 ACU` + `pauseAfter`
91
+ // auto-pause when idle. The first ExecuteStatement after a pause fails with
92
+ // "...resuming after being auto-paused. Please wait a few seconds and try
93
+ // again." while the cluster warms up (typically 15-30s). Also retry on
94
+ // transient network errors and throttles — the Data API is backed by a
95
+ // managed HTTPS endpoint and can flake under load.
96
+ const RESUMING_PATTERN = /resuming after being auto-paused|DatabaseResumingException|DatabaseNotFoundException|ThrottlingException|ServiceUnavailable/i;
97
+ async function sendWithResume(send, opts = {}) {
98
+ const attempts = opts.attempts ?? 10;
99
+ const baseDelayMs = opts.baseDelayMs ?? 5_000;
100
+ let lastErr;
101
+ for (let i = 0; i < attempts; i += 1) {
102
+ try {
103
+ return await send();
104
+ }
105
+ catch (err) {
106
+ lastErr = err;
107
+ const message = err instanceof Error ? err.message : String(err);
108
+ if (!RESUMING_PATTERN.test(message) || i === attempts - 1)
109
+ throw err;
110
+ // Linear backoff capped at ~30s per wait. Aurora resume SLA is 15-30s
111
+ // total so ~5 attempts at 5-15s each typically clears it.
112
+ const delay = Math.min(baseDelayMs * (i + 1), 30_000);
113
+ await new Promise((resolve) => setTimeout(resolve, delay));
114
+ }
115
+ }
116
+ throw lastErr;
117
+ }
118
+ class RdsDataApiExecutor {
119
+ client;
120
+ resourceArn;
121
+ secretArn;
122
+ ExecuteStatementCommand;
123
+ constructor(client, resourceArn, secretArn, ExecuteStatementCommand) {
124
+ this.client = client;
125
+ this.resourceArn = resourceArn;
126
+ this.secretArn = secretArn;
127
+ this.ExecuteStatementCommand = ExecuteStatementCommand;
128
+ }
129
+ async execute(database, sql) {
130
+ await sendWithResume(() => this.client.send(new this.ExecuteStatementCommand({
131
+ resourceArn: this.resourceArn,
132
+ secretArn: this.secretArn,
133
+ database,
134
+ sql,
135
+ })));
136
+ }
137
+ async exists(database, existsSql) {
138
+ const res = await sendWithResume(() => this.client.send(new this.ExecuteStatementCommand({
139
+ resourceArn: this.resourceArn,
140
+ secretArn: this.secretArn,
141
+ database,
142
+ sql: existsSql,
143
+ })));
144
+ const records = res.records ?? [];
145
+ return records.length > 0;
146
+ }
147
+ }
148
+ exports.RdsDataApiExecutor = RdsDataApiExecutor;
149
+ // SQL generators. Exposed for tests so we can assert on the exact strings
150
+ // the provider emits.
151
+ function createDatabaseSql(database) {
152
+ return `CREATE DATABASE "${database}"`;
153
+ }
154
+ function databaseExistsSql(database) {
155
+ return `SELECT 1 FROM pg_database WHERE datname = '${database.replace(/'/g, "''")}'`;
156
+ }
157
+ function roleExistsSql(role) {
158
+ return `SELECT 1 FROM pg_roles WHERE rolname = '${role.replace(/'/g, "''")}'`;
159
+ }
160
+ function createRoleSql(role, password) {
161
+ // Password embedded literally — escape single quotes. The provider runs
162
+ // once per resource; Pulumi ensures stable state so this doesn't leak to
163
+ // logs on repeated apply cycles when the role already exists.
164
+ const escapedPassword = password.replace(/'/g, "''");
165
+ return `CREATE ROLE "${role}" WITH LOGIN PASSWORD '${escapedPassword}'`;
166
+ }
167
+ function alterRolePasswordSql(role, password) {
168
+ const escapedPassword = password.replace(/'/g, "''");
169
+ return `ALTER ROLE "${role}" WITH PASSWORD '${escapedPassword}'`;
170
+ }
171
+ function grantScopedAccessSql(database, readwriteRole, readonlyRole) {
172
+ // Revoke default public, grant connect to both roles, grant DML/DDL to RW,
173
+ // and set default privileges so every table/sequence the RW role creates
174
+ // via migrations is immediately readable by the RO role.
175
+ //
176
+ // `GRANT "<rw>" TO CURRENT_USER` is required before `ALTER DEFAULT
177
+ // PRIVILEGES FOR ROLE "<rw>"` — Postgres only lets you set default
178
+ // privileges for roles you are a member of (error 42501 otherwise).
179
+ // `CURRENT_USER` here resolves to Aurora's master user that the Data API
180
+ // authenticates as (default `postgres`).
181
+ //
182
+ // Returned as individual statements — the RDS Data API's ExecuteStatement
183
+ // only accepts one SQL statement per call ("Multistatements aren't
184
+ // supported"), so the provider iterates this list.
185
+ return [
186
+ `REVOKE ALL ON DATABASE "${database}" FROM PUBLIC`,
187
+ `GRANT CONNECT ON DATABASE "${database}" TO "${readwriteRole}", "${readonlyRole}"`,
188
+ // Database-level CREATE lets the RW role create new schemas. Drizzle's
189
+ // Postgres migrator starts with `CREATE SCHEMA IF NOT EXISTS "drizzle"`
190
+ // for its `__drizzle_migrations` bookkeeping table; without this grant
191
+ // every fresh `db-migrate` would bail with `permission denied for
192
+ // database ...` before any user migration runs.
193
+ `GRANT CREATE ON DATABASE "${database}" TO "${readwriteRole}"`,
194
+ `GRANT ALL ON SCHEMA public TO "${readwriteRole}"`,
195
+ `GRANT USAGE ON SCHEMA public TO "${readonlyRole}"`,
196
+ `GRANT "${readwriteRole}" TO CURRENT_USER`,
197
+ `ALTER DEFAULT PRIVILEGES FOR ROLE "${readwriteRole}" IN SCHEMA public GRANT ALL ON TABLES TO "${readwriteRole}"`,
198
+ `ALTER DEFAULT PRIVILEGES FOR ROLE "${readwriteRole}" IN SCHEMA public GRANT SELECT ON TABLES TO "${readonlyRole}"`,
199
+ `ALTER DEFAULT PRIVILEGES FOR ROLE "${readwriteRole}" IN SCHEMA public GRANT USAGE, SELECT ON SEQUENCES TO "${readonlyRole}"`,
200
+ ];
201
+ }
202
+ // 32 chars of url-safe alphanumerics. Postgres handles this literal safely in
203
+ // a single-quoted password string (no escape needed) and it's strong enough
204
+ // for an app-scoped role in an RDS-Proxy-fronted cluster.
205
+ function defaultPasswordGenerator() {
206
+ return (0, node_crypto_1.randomBytes)(24)
207
+ .toString('base64')
208
+ .replace(/[^A-Za-z0-9]/g, '')
209
+ .slice(0, 32)
210
+ .padEnd(32, 'a');
211
+ }
212
+ class AuroraLogicalDbProvider {
213
+ executorFactory;
214
+ passwordGenerator;
215
+ constructor(options = {}) {
216
+ this.executorFactory = options.executorFactory;
217
+ this.passwordGenerator =
218
+ options.passwordGenerator ?? defaultPasswordGenerator;
219
+ }
220
+ async buildExecutor(inputs) {
221
+ if (this.executorFactory)
222
+ return this.executorFactory(inputs);
223
+ // Pulumi serializes the complete dynamic-provider closure before running
224
+ // any lifecycle method. A static AWS SDK value here pulls the SDK's
225
+ // transpiled tslib helpers into that closure; Node 24 exposes a free
226
+ // AsyncIterator reference that Pulumi cannot serialize. The Nx package is
227
+ // emitted at ES2022 so this method remains native async, and the SDK is
228
+ // resolved only while the provider executes. TypeScript rewrites a native
229
+ // dynamic import to require() for this CommonJS package, and SST then wraps
230
+ // that require in an unserializable bundle helper. Constructing the import
231
+ // expression at runtime preserves the module boundary through both builds.
232
+ // The serialized closure contains only this string and a standard global.
233
+ const importModule = Function('specifier', 'return import(specifier);');
234
+ const { ExecuteStatementCommand, RDSDataClient } = await importModule('@aws-sdk/client-rds-data');
235
+ const client = new RDSDataClient({});
236
+ return new RdsDataApiExecutor(client, inputs.clusterArn, inputs.masterSecretArn, ExecuteStatementCommand);
237
+ }
238
+ // Generates a password and registers it with the caller's in-scope secret
239
+ // collector so `redactDataApiError` can redact it by VALUE if any later
240
+ // Data API call in the same lifecycle method throws.
241
+ generateSecret(secretsInScope) {
242
+ const value = this.passwordGenerator();
243
+ secretsInScope.push(value);
244
+ return value;
245
+ }
246
+ async create(inputs) {
247
+ const secretsInScope = [];
248
+ try {
249
+ return await this.createInternal(inputs, secretsInScope);
250
+ }
251
+ catch (error) {
252
+ throw redactDataApiError(error, secretsInScope);
253
+ }
254
+ }
255
+ async createInternal(inputs, secretsInScope) {
256
+ const executor = await this.buildExecutor(inputs);
257
+ const { database, readwriteRole, readonlyRole } = inputs;
258
+ // Generate passwords INSIDE the provider and persist them in `outs`. Pulumi
259
+ // stores outs in state, so on subsequent applies we surface the same
260
+ // values via `update`'s `olds`. This avoids a hard dep on `@pulumi/random`.
261
+ const readwritePassword = this.generateSecret(secretsInScope);
262
+ const readonlyPassword = this.generateSecret(secretsInScope);
263
+ // CREATE DATABASE can't run in a transaction — issue via Data API
264
+ // ExecuteStatement which auto-commits each call.
265
+ const dbExists = await executor.exists('postgres', databaseExistsSql(database));
266
+ if (!dbExists) {
267
+ await executor.execute('postgres', createDatabaseSql(database));
268
+ }
269
+ // Role creation inside the new database. When the role doesn't exist we
270
+ // issue CREATE ROLE with the freshly generated password. When it DOES
271
+ // exist (retained from a previous deploy, or state was lost and this is
272
+ // a re-create against retained resources) we MUST issue ALTER ROLE so
273
+ // Postgres matches the password we're about to return in outs +
274
+ // advertise through Secrets Manager + the Linkable. Without this,
275
+ // pg_authid keeps the old hash while everything downstream advertises
276
+ // the new one — authentication fails permanently.
277
+ const rwExists = await executor.exists(database, roleExistsSql(readwriteRole));
278
+ if (rwExists) {
279
+ await executor.execute(database, alterRolePasswordSql(readwriteRole, readwritePassword));
280
+ }
281
+ else {
282
+ await executor.execute(database, createRoleSql(readwriteRole, readwritePassword));
283
+ }
284
+ const roExists = await executor.exists(database, roleExistsSql(readonlyRole));
285
+ if (roExists) {
286
+ await executor.execute(database, alterRolePasswordSql(readonlyRole, readonlyPassword));
287
+ }
288
+ else {
289
+ await executor.execute(database, createRoleSql(readonlyRole, readonlyPassword));
290
+ }
291
+ for (const stmt of grantScopedAccessSql(database, readwriteRole, readonlyRole)) {
292
+ await executor.execute(database, stmt);
293
+ }
294
+ return {
295
+ id: `${inputs.clusterArn}:${database}`,
296
+ outs: {
297
+ ...inputs,
298
+ readwritePassword,
299
+ readonlyPassword,
300
+ },
301
+ };
302
+ }
303
+ async update(_id, olds, news) {
304
+ // Stored state passwords are in scope for redaction: a failing statement
305
+ // (or a Postgres echo of one) can reference the previous values as well
306
+ // as any freshly regenerated ones.
307
+ const secretsInScope = [
308
+ olds.readwritePassword,
309
+ olds.readonlyPassword,
310
+ ].filter((value) => typeof value === 'string');
311
+ try {
312
+ return await this.updateInternal(olds, news, secretsInScope);
313
+ }
314
+ catch (error) {
315
+ throw redactDataApiError(error, secretsInScope);
316
+ }
317
+ }
318
+ async updateInternal(olds, news, secretsInScope) {
319
+ const executor = await this.buildExecutor(news);
320
+ // Passwords are not re-keyed on a normal update. Carry them forward from
321
+ // state so the resource output surface stays stable.
322
+ //
323
+ // Rotation: when `rotationToken` CHANGES between deploys, drop the stored
324
+ // values so the branches below regenerate both passwords and force
325
+ // Postgres to match via ALTER ROLE. This is the sanctioned one-line-diff
326
+ // rotation path (see the runbook in `packages/data/README.md`) — required
327
+ // for stages deployed before generated passwords were marked as Pulumi
328
+ // secret outputs, whose state history/backups may hold plaintext values.
329
+ //
330
+ // Self-heal for the state-loss edge case: if `olds.*Password` is missing
331
+ // (resource originally created without the output placeholders in args,
332
+ // so Pulumi never serialized the generated passwords to state), we
333
+ // regenerate and force Postgres to match via ALTER ROLE. Without this
334
+ // branch the Linkable + Secret would advertise an empty password while
335
+ // pg_authid still has the original — authentication fails permanently.
336
+ const rotationRequested = (olds.rotationToken ?? '') !== (news.rotationToken ?? '');
337
+ let readwritePassword = rotationRequested ? '' : olds.readwritePassword;
338
+ let readonlyPassword = rotationRequested ? '' : olds.readonlyPassword;
339
+ if (!readwritePassword) {
340
+ readwritePassword = this.generateSecret(secretsInScope);
341
+ await executor.execute(news.database, alterRolePasswordSql(news.readwriteRole, readwritePassword));
342
+ }
343
+ if (!readonlyPassword) {
344
+ readonlyPassword = this.generateSecret(secretsInScope);
345
+ await executor.execute(news.database, alterRolePasswordSql(news.readonlyRole, readonlyPassword));
346
+ }
347
+ // Re-apply the grant block — idempotent on Postgres and protects against
348
+ // drift if someone touched privileges out-of-band.
349
+ for (const stmt of grantScopedAccessSql(news.database, news.readwriteRole, news.readonlyRole)) {
350
+ await executor.execute(news.database, stmt);
351
+ }
352
+ return {
353
+ outs: {
354
+ ...news,
355
+ readwritePassword,
356
+ readonlyPassword,
357
+ },
358
+ };
359
+ }
360
+ async delete(_id, props) {
361
+ const secretsInScope = [
362
+ props.readwritePassword,
363
+ props.readonlyPassword,
364
+ ].filter((value) => typeof value === 'string');
365
+ try {
366
+ await this.deleteInternal(props);
367
+ }
368
+ catch (error) {
369
+ throw redactDataApiError(error, secretsInScope);
370
+ }
371
+ }
372
+ async deleteInternal(props) {
373
+ if (props.removalPolicy !== 'destroy') {
374
+ // Default retain — no-op. Resource is removed from Pulumi state but
375
+ // the database + roles stay in the cluster. Safety default for production.
376
+ return;
377
+ }
378
+ const executor = await this.buildExecutor(props);
379
+ // Drop in reverse order of create. FORCE disconnects active sessions.
380
+ await executor.execute('postgres', `REVOKE ALL ON DATABASE "${props.database}" FROM "${props.readwriteRole}", "${props.readonlyRole}"`);
381
+ await executor.execute('postgres', `DROP DATABASE IF EXISTS "${props.database}" WITH (FORCE)`);
382
+ // create() did `GRANT "<rw>" TO CURRENT_USER` so the master user could
383
+ // ALTER DEFAULT PRIVILEGES on that role. That membership has to be
384
+ // revoked before DROP ROLE — Postgres refuses to drop a role that still
385
+ // has dependent privileges. IF EXISTS on REVOKE keeps this idempotent
386
+ // for retained-create paths that never hit the grant.
387
+ await executor.execute('postgres', `REVOKE "${props.readwriteRole}" FROM CURRENT_USER`);
388
+ await executor.execute('postgres', `DROP ROLE IF EXISTS "${props.readwriteRole}"`);
389
+ await executor.execute('postgres', `DROP ROLE IF EXISTS "${props.readonlyRole}"`);
390
+ }
391
+ }
392
+ exports.AuroraLogicalDbProvider = AuroraLogicalDbProvider;
393
+ function createAuroraLogicalDbResource(options) {
394
+ const Resource = $util.dynamic.Resource;
395
+ const additionalSecretOutputs = [
396
+ ...new Set([
397
+ ...(options.opts?.additionalSecretOutputs ?? []),
398
+ ...GENERATED_PASSWORD_SECRET_OUTPUTS,
399
+ ]),
400
+ ];
401
+ // Pulumi convention for dynamic.Resource: fields that are produced by the
402
+ // provider's create() (i.e. in `outs` but not in caller-supplied `args`)
403
+ // must be declared on the constructor args as `undefined` placeholders —
404
+ // otherwise Pulumi doesn't surface them as `Output<T>` on the resource,
405
+ // and consumers that read them (e.g. `logicalDb.readwritePassword`) get
406
+ // unresolved wrappers instead of the resolved strings.
407
+ //
408
+ // See SST platform's own providers (e.g. cloudflare/worker-url.ts) for the
409
+ // same pattern: `{ ...args, url: undefined }`.
410
+ return new Resource(new AuroraLogicalDbProvider(), options.name, {
411
+ ...options.args,
412
+ readwritePassword: undefined,
413
+ readonlyPassword: undefined,
414
+ }, {
415
+ ...options.opts,
416
+ additionalSecretOutputs,
417
+ });
418
+ }
419
+ //# sourceMappingURL=aurora-logical-database.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aurora-logical-database.js","sourceRoot":"","sources":["../../../../../packages/nx/src/foundation/aurora-logical-database.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ import { type FoundationRequirement, type StandardFoundationCapability } from './requirements.js';
2
+ export declare const FOUNDATION_SSM_NAMESPACE: "/ebk";
3
+ export declare const FOUNDATION_SSM_SCHEMA_VERSION: 2;
4
+ export declare const FOUNDATION_SSM_KEYS: {
5
+ readonly alertTopicArn: "alertTopicArn";
6
+ readonly capabilities: "capabilities";
7
+ readonly clusterId: "clusterId";
8
+ readonly contractVersion: "contractVersion";
9
+ readonly databaseClusterArn: "databaseClusterArn";
10
+ readonly databaseClusterId: "databaseClusterId";
11
+ readonly databaseMasterSecretArn: "databaseMasterSecretArn";
12
+ readonly eventBusArn: "eventBusArn";
13
+ readonly eventBusName: "eventBusName";
14
+ readonly hasPublicDomain: "hasPublicDomain";
15
+ readonly identityUserPoolArn: "identityUserPoolArn";
16
+ readonly identityUserPoolId: "identityUserPoolId";
17
+ readonly rootDomain: "rootDomain";
18
+ readonly routerDistributionId: "routerDistributionId";
19
+ readonly routerUrl: "routerUrl";
20
+ readonly schemaVersion: "schemaVersion";
21
+ readonly vpcId: "vpcId";
22
+ };
23
+ export type FoundationSsmKey = keyof typeof FOUNDATION_SSM_KEYS;
24
+ export declare const FOUNDATION_REQUIRED_SSM_KEYS: FoundationSsmKey[];
25
+ export declare const STANDARD_FOUNDATION_REQUIREMENT: FoundationRequirement;
26
+ export interface FoundationDiscovery {
27
+ alertTopicArn: string;
28
+ capabilities: StandardFoundationCapability[];
29
+ clusterId: string;
30
+ contractVersion: string;
31
+ databaseClusterArn: string;
32
+ databaseClusterId: string;
33
+ databaseMasterSecretArn: string;
34
+ eventBusArn: string;
35
+ eventBusName: string;
36
+ hasPublicDomain: boolean;
37
+ identityUserPoolArn: string;
38
+ identityUserPoolId: string;
39
+ rootDomain?: string;
40
+ routerDistributionId: string;
41
+ routerUrl: string;
42
+ schemaVersion: typeof FOUNDATION_SSM_SCHEMA_VERSION;
43
+ vpcId: string;
44
+ }
45
+ export interface ProductSliceRegistration {
46
+ consumerStage: string;
47
+ foundationContract: string;
48
+ foundationStage: string;
49
+ name: string;
50
+ registrationVersion: 1;
51
+ }
52
+ export declare function foundationSsmStageRoot(stage: string): string;
53
+ export declare function foundationSsmPath(stage: string, key: FoundationSsmKey): string;
54
+ export declare function productSliceRegistrationRoot(foundationStage: string): string;
55
+ export declare function productSliceRegistrationPath(foundationStage: string, consumerStage: string, slice: string): string;
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.STANDARD_FOUNDATION_REQUIREMENT = exports.FOUNDATION_REQUIRED_SSM_KEYS = exports.FOUNDATION_SSM_KEYS = exports.FOUNDATION_SSM_SCHEMA_VERSION = exports.FOUNDATION_SSM_NAMESPACE = void 0;
4
+ exports.foundationSsmStageRoot = foundationSsmStageRoot;
5
+ exports.foundationSsmPath = foundationSsmPath;
6
+ exports.productSliceRegistrationRoot = productSliceRegistrationRoot;
7
+ exports.productSliceRegistrationPath = productSliceRegistrationPath;
8
+ const requirements_js_1 = require("./requirements.js");
9
+ const stages_js_1 = require("./stages.js");
10
+ exports.FOUNDATION_SSM_NAMESPACE = '/ebk';
11
+ exports.FOUNDATION_SSM_SCHEMA_VERSION = 2;
12
+ exports.FOUNDATION_SSM_KEYS = {
13
+ alertTopicArn: 'alertTopicArn',
14
+ capabilities: 'capabilities',
15
+ clusterId: 'clusterId',
16
+ contractVersion: 'contractVersion',
17
+ databaseClusterArn: 'databaseClusterArn',
18
+ databaseClusterId: 'databaseClusterId',
19
+ databaseMasterSecretArn: 'databaseMasterSecretArn',
20
+ eventBusArn: 'eventBusArn',
21
+ eventBusName: 'eventBusName',
22
+ hasPublicDomain: 'hasPublicDomain',
23
+ identityUserPoolArn: 'identityUserPoolArn',
24
+ identityUserPoolId: 'identityUserPoolId',
25
+ rootDomain: 'rootDomain',
26
+ routerDistributionId: 'routerDistributionId',
27
+ routerUrl: 'routerUrl',
28
+ schemaVersion: 'schemaVersion',
29
+ vpcId: 'vpcId',
30
+ };
31
+ exports.FOUNDATION_REQUIRED_SSM_KEYS = Object.keys(exports.FOUNDATION_SSM_KEYS);
32
+ exports.STANDARD_FOUNDATION_REQUIREMENT = {
33
+ capabilities: [...requirements_js_1.STANDARD_FOUNDATION_CAPABILITIES],
34
+ contract: '^1.0.0',
35
+ };
36
+ function requirePathSegment(value, label) {
37
+ const normalized = value.trim();
38
+ if (!/^[a-z0-9][a-z0-9-]*$/.test(normalized)) {
39
+ throw new Error(`${label} must use lowercase letters, numbers, and hyphens.`);
40
+ }
41
+ return normalized;
42
+ }
43
+ function foundationSsmStageRoot(stage) {
44
+ return `${exports.FOUNDATION_SSM_NAMESPACE}/${(0, stages_js_1.requireFoundationStage)(stage)}/foundation`;
45
+ }
46
+ function foundationSsmPath(stage, key) {
47
+ return `${foundationSsmStageRoot(stage)}/${exports.FOUNDATION_SSM_KEYS[key]}`;
48
+ }
49
+ function productSliceRegistrationRoot(foundationStage) {
50
+ return `${foundationSsmStageRoot(foundationStage)}/product-slices`;
51
+ }
52
+ function productSliceRegistrationPath(foundationStage, consumerStage, slice) {
53
+ return `${productSliceRegistrationRoot(foundationStage)}/${(0, stages_js_1.requireStage)(consumerStage, 'Consumer stage')}/${requirePathSegment(slice, 'Product Slice name')}`;
54
+ }
55
+ //# sourceMappingURL=discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../../../../packages/nx/src/foundation/discovery.ts"],"names":[],"mappings":";;;AA+EA,wDAEC;AAED,8CAKC;AAED,oEAEC;AAED,oEAMC;AApGD,uDAI2B;AAC3B,2CAAmE;AAEtD,QAAA,wBAAwB,GAAG,MAAe,CAAC;AAC3C,QAAA,6BAA6B,GAAG,CAAU,CAAC;AAE3C,QAAA,mBAAmB,GAAG;IACjC,aAAa,EAAE,eAAe;IAC9B,YAAY,EAAE,cAAc;IAC5B,SAAS,EAAE,WAAW;IACtB,eAAe,EAAE,iBAAiB;IAClC,kBAAkB,EAAE,oBAAoB;IACxC,iBAAiB,EAAE,mBAAmB;IACtC,uBAAuB,EAAE,yBAAyB;IAClD,WAAW,EAAE,aAAa;IAC1B,YAAY,EAAE,cAAc;IAC5B,eAAe,EAAE,iBAAiB;IAClC,mBAAmB,EAAE,qBAAqB;IAC1C,kBAAkB,EAAE,oBAAoB;IACxC,UAAU,EAAE,YAAY;IACxB,oBAAoB,EAAE,sBAAsB;IAC5C,SAAS,EAAE,WAAW;IACtB,aAAa,EAAE,eAAe;IAC9B,KAAK,EAAE,OAAO;CACN,CAAC;AAIE,QAAA,4BAA4B,GAAG,MAAM,CAAC,IAAI,CACrD,2BAAmB,CACE,CAAC;AAEX,QAAA,+BAA+B,GAA0B;IACpE,YAAY,EAAE,CAAC,GAAG,kDAAgC,CAAC;IACnD,QAAQ,EAAE,QAAQ;CACnB,CAAC;AA8BF,SAAS,kBAAkB,CAAC,KAAa,EAAE,KAAa;IACtD,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAChC,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,KAAK,CACb,GAAG,KAAK,oDAAoD,CAC7D,CAAC;IACJ,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,SAAgB,sBAAsB,CAAC,KAAa;IAClD,OAAO,GAAG,gCAAwB,IAAI,IAAA,kCAAsB,EAAC,KAAK,CAAC,aAAa,CAAC;AACnF,CAAC;AAED,SAAgB,iBAAiB,CAC/B,KAAa,EACb,GAAqB;IAErB,OAAO,GAAG,sBAAsB,CAAC,KAAK,CAAC,IAAI,2BAAmB,CAAC,GAAG,CAAC,EAAE,CAAC;AACxE,CAAC;AAED,SAAgB,4BAA4B,CAAC,eAAuB;IAClE,OAAO,GAAG,sBAAsB,CAAC,eAAe,CAAC,iBAAiB,CAAC;AACrE,CAAC;AAED,SAAgB,4BAA4B,CAC1C,eAAuB,EACvB,aAAqB,EACrB,KAAa;IAEb,OAAO,GAAG,4BAA4B,CAAC,eAAe,CAAC,IAAI,IAAA,wBAAY,EAAC,aAAa,EAAE,gBAAgB,CAAC,IAAI,kBAAkB,CAAC,KAAK,EAAE,oBAAoB,CAAC,EAAE,CAAC;AAChK,CAAC"}
@@ -0,0 +1,6 @@
1
+ export * from './discovery.js';
2
+ export * from './local-database-contract.js';
3
+ export * from './provision-database-bindings.js';
4
+ export * from './provision-logical-database.js';
5
+ export * from './requirements.js';
6
+ export * from './stages.js';
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./discovery.js"), exports);
5
+ tslib_1.__exportStar(require("./local-database-contract.js"), exports);
6
+ tslib_1.__exportStar(require("./provision-database-bindings.js"), exports);
7
+ tslib_1.__exportStar(require("./provision-logical-database.js"), exports);
8
+ tslib_1.__exportStar(require("./requirements.js"), exports);
9
+ tslib_1.__exportStar(require("./stages.js"), exports);
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/nx/src/foundation/index.ts"],"names":[],"mappings":";;;AAAA,yDAA+B;AAC/B,uEAA6C;AAC7C,2EAAiD;AACjD,0EAAgD;AAChD,4DAAkC;AAClC,sDAA4B"}
@@ -0,0 +1,30 @@
1
+ export interface LocalDatabaseContractOptions {
2
+ database: string;
3
+ password?: string;
4
+ port?: number;
5
+ slice: string;
6
+ }
7
+ export interface LocalDatabaseContract {
8
+ database: string;
9
+ host: '127.0.0.1';
10
+ password: string;
11
+ port: number;
12
+ username: string;
13
+ }
14
+ export declare const POSTGRES_IDENTIFIER_MAX_BYTES = 63;
15
+ export interface LogicalDatabaseIdentifiers {
16
+ database: string;
17
+ localDatabase: string;
18
+ localReadwriteRole: string;
19
+ readonlyRole: string;
20
+ readwriteRole: string;
21
+ }
22
+ export declare function normalizePostgresIdentifier(input: string): string;
23
+ export declare function postgresIdentifierByteLength(identifier: string): number;
24
+ export declare function assertPostgresIdentifierLength(identifier: string, label: string): void;
25
+ export declare function resolveLogicalDatabaseIdentifiers(options: {
26
+ database: string;
27
+ slice: string;
28
+ stage: string;
29
+ }): LogicalDatabaseIdentifiers;
30
+ export declare function resolveLocalDatabaseContract(options: LocalDatabaseContractOptions): LocalDatabaseContract;