koppler 0.0.0-stage → 0.0.2

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 (225) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +101 -2
  3. package/bin/run-logged +16 -0
  4. package/bin/secret-list +7 -0
  5. package/bin/secret-psql +41 -0
  6. package/bin/secret-set +17 -0
  7. package/bin/secret-store +82 -0
  8. package/bin/secret-test +10 -0
  9. package/bin/with-secrets +25 -0
  10. package/dist/.built +1 -0
  11. package/dist/cli/agent.js +144 -0
  12. package/dist/cli/agent.js.map +1 -0
  13. package/dist/cli/doctor.js +173 -0
  14. package/dist/cli/doctor.js.map +1 -0
  15. package/dist/cli/mcp.js +204 -0
  16. package/dist/cli/mcp.js.map +1 -0
  17. package/dist/cli/output.js +37 -0
  18. package/dist/cli/output.js.map +1 -0
  19. package/dist/cli/records.js +121 -0
  20. package/dist/cli/records.js.map +1 -0
  21. package/dist/cli/running.js +270 -0
  22. package/dist/cli/running.js.map +1 -0
  23. package/dist/cli/shell.js +43 -0
  24. package/dist/cli/shell.js.map +1 -0
  25. package/dist/cli/wait.js +59 -0
  26. package/dist/cli/wait.js.map +1 -0
  27. package/dist/core/addresses.js +55 -0
  28. package/dist/core/addresses.js.map +1 -0
  29. package/dist/core/arrange.js +329 -0
  30. package/dist/core/arrange.js.map +1 -0
  31. package/dist/core/cables.js +158 -0
  32. package/dist/core/cables.js.map +1 -0
  33. package/dist/core/expressions.js +72 -0
  34. package/dist/core/expressions.js.map +1 -0
  35. package/dist/core/frameworks.js +13 -0
  36. package/dist/core/frameworks.js.map +1 -0
  37. package/dist/core/kinds.js +244 -0
  38. package/dist/core/kinds.js.map +1 -0
  39. package/dist/core/launch.js +181 -0
  40. package/dist/core/launch.js.map +1 -0
  41. package/dist/core/logfmt.js +144 -0
  42. package/dist/core/logfmt.js.map +1 -0
  43. package/dist/core/mock.js +27 -0
  44. package/dist/core/mock.js.map +1 -0
  45. package/dist/core/plan.js +147 -0
  46. package/dist/core/plan.js.map +1 -0
  47. package/dist/core/ports.js +155 -0
  48. package/dist/core/ports.js.map +1 -0
  49. package/dist/core/presets.js +186 -0
  50. package/dist/core/presets.js.map +1 -0
  51. package/dist/core/secret-types.js +3 -0
  52. package/dist/core/secret-types.js.map +1 -0
  53. package/dist/core/sign-in.js +30 -0
  54. package/dist/core/sign-in.js.map +1 -0
  55. package/dist/core/stack-path.js +64 -0
  56. package/dist/core/stack-path.js.map +1 -0
  57. package/dist/core/stack.js +509 -0
  58. package/dist/core/stack.js.map +1 -0
  59. package/dist/core/terraform.js +393 -0
  60. package/dist/core/terraform.js.map +1 -0
  61. package/dist/data.js +37 -0
  62. package/dist/data.js.map +1 -0
  63. package/dist/engine/actions.js +99 -0
  64. package/dist/engine/actions.js.map +1 -0
  65. package/dist/engine/app-commands.js +106 -0
  66. package/dist/engine/app-commands.js.map +1 -0
  67. package/dist/engine/app-start.js +167 -0
  68. package/dist/engine/app-start.js.map +1 -0
  69. package/dist/engine/app-state.js +43 -0
  70. package/dist/engine/app-state.js.map +1 -0
  71. package/dist/engine/boards.js +219 -0
  72. package/dist/engine/boards.js.map +1 -0
  73. package/dist/engine/branch.js +194 -0
  74. package/dist/engine/branch.js.map +1 -0
  75. package/dist/engine/browser-console.js +45 -0
  76. package/dist/engine/browser-console.js.map +1 -0
  77. package/dist/engine/calls.js +97 -0
  78. package/dist/engine/calls.js.map +1 -0
  79. package/dist/engine/checks.js +270 -0
  80. package/dist/engine/checks.js.map +1 -0
  81. package/dist/engine/clones.js +67 -0
  82. package/dist/engine/clones.js.map +1 -0
  83. package/dist/engine/config.js +26 -0
  84. package/dist/engine/config.js.map +1 -0
  85. package/dist/engine/deployed.js +488 -0
  86. package/dist/engine/deployed.js.map +1 -0
  87. package/dist/engine/devices.js +81 -0
  88. package/dist/engine/devices.js.map +1 -0
  89. package/dist/engine/discover.js +236 -0
  90. package/dist/engine/discover.js.map +1 -0
  91. package/dist/engine/down.js +253 -0
  92. package/dist/engine/down.js.map +1 -0
  93. package/dist/engine/history.js +215 -0
  94. package/dist/engine/history.js.map +1 -0
  95. package/dist/engine/investigate.js +278 -0
  96. package/dist/engine/investigate.js.map +1 -0
  97. package/dist/engine/libraries.js +129 -0
  98. package/dist/engine/libraries.js.map +1 -0
  99. package/dist/engine/linked.js +146 -0
  100. package/dist/engine/linked.js.map +1 -0
  101. package/dist/engine/listen.js +223 -0
  102. package/dist/engine/listen.js.map +1 -0
  103. package/dist/engine/locks.js +38 -0
  104. package/dist/engine/locks.js.map +1 -0
  105. package/dist/engine/messages.js +177 -0
  106. package/dist/engine/messages.js.map +1 -0
  107. package/dist/engine/needs.js +363 -0
  108. package/dist/engine/needs.js.map +1 -0
  109. package/dist/engine/processes.js +350 -0
  110. package/dist/engine/processes.js.map +1 -0
  111. package/dist/engine/query.js +241 -0
  112. package/dist/engine/query.js.map +1 -0
  113. package/dist/engine/queues.js +100 -0
  114. package/dist/engine/queues.js.map +1 -0
  115. package/dist/engine/recipes.js +248 -0
  116. package/dist/engine/recipes.js.map +1 -0
  117. package/dist/engine/reload.js +32 -0
  118. package/dist/engine/reload.js.map +1 -0
  119. package/dist/engine/repos.js +214 -0
  120. package/dist/engine/repos.js.map +1 -0
  121. package/dist/engine/research.js +134 -0
  122. package/dist/engine/research.js.map +1 -0
  123. package/dist/engine/run-logs.js +79 -0
  124. package/dist/engine/run-logs.js.map +1 -0
  125. package/dist/engine/run.js +54 -0
  126. package/dist/engine/run.js.map +1 -0
  127. package/dist/engine/runs.js +223 -0
  128. package/dist/engine/runs.js.map +1 -0
  129. package/dist/engine/session.js +130 -0
  130. package/dist/engine/session.js.map +1 -0
  131. package/dist/engine/share.js +124 -0
  132. package/dist/engine/share.js.map +1 -0
  133. package/dist/engine/stack-file.js +206 -0
  134. package/dist/engine/stack-file.js.map +1 -0
  135. package/dist/engine/stack-share.js +86 -0
  136. package/dist/engine/stack-share.js.map +1 -0
  137. package/dist/engine/stacks.js +143 -0
  138. package/dist/engine/stacks.js.map +1 -0
  139. package/dist/engine/sync.js +214 -0
  140. package/dist/engine/sync.js.map +1 -0
  141. package/dist/engine/traces.js +65 -0
  142. package/dist/engine/traces.js.map +1 -0
  143. package/dist/engine/up.js +621 -0
  144. package/dist/engine/up.js.map +1 -0
  145. package/dist/engine/watch.js +71 -0
  146. package/dist/engine/watch.js.map +1 -0
  147. package/dist/engine/wire.js +120 -0
  148. package/dist/engine/wire.js.map +1 -0
  149. package/dist/failure.js +16 -0
  150. package/dist/failure.js.map +1 -0
  151. package/dist/github.js +95 -0
  152. package/dist/github.js.map +1 -0
  153. package/dist/ids.js +6 -0
  154. package/dist/ids.js.map +1 -0
  155. package/dist/json-files.js +36 -0
  156. package/dist/json-files.js.map +1 -0
  157. package/dist/koppler.mjs +840 -0
  158. package/dist/koppler.mjs.map +1 -0
  159. package/dist/lambda-local.mjs +250 -0
  160. package/dist/lambda-local.mjs.map +1 -0
  161. package/dist/lambda-secrets-proxy.go +31 -0
  162. package/dist/mock-server.mjs +23 -0
  163. package/dist/mock-server.mjs.map +1 -0
  164. package/dist/page/assets/JetBrainsMono-cyrillic-D2jMJ_bk.woff2 +0 -0
  165. package/dist/page/assets/JetBrainsMono-greek-D2nYnAec.woff2 +0 -0
  166. package/dist/page/assets/JetBrainsMono-latin-Db4Uuiha.woff2 +0 -0
  167. package/dist/page/assets/JetBrainsMono-latin-ext-Bnd2h4Br.woff2 +0 -0
  168. package/dist/page/assets/JetBrainsMono-vietnamese-CNlsqbWb.woff2 +0 -0
  169. package/dist/page/assets/SchibstedGrotesk-latin-DxefFeRw.woff2 +0 -0
  170. package/dist/page/assets/SchibstedGrotesk-latin-ext-CnpJE18X.woff2 +0 -0
  171. package/dist/page/assets/index-Bkj_pX35.js +42 -0
  172. package/dist/page/assets/index-Dq45jswH.css +1 -0
  173. package/dist/page/index.html +14 -0
  174. package/dist/page/theme.js +8 -0
  175. package/dist/paths.js +19 -0
  176. package/dist/paths.js.map +1 -0
  177. package/dist/safe-env.js +73 -0
  178. package/dist/safe-env.js.map +1 -0
  179. package/dist/sam-local.mjs +135 -0
  180. package/dist/sam-local.mjs.map +1 -0
  181. package/dist/scrub.js +87 -0
  182. package/dist/scrub.js.map +1 -0
  183. package/dist/secret-check.mjs +262 -0
  184. package/dist/secret-check.mjs.map +1 -0
  185. package/dist/server/browser-console.js +117 -0
  186. package/dist/server/browser-console.js.map +1 -0
  187. package/dist/server/cable-test.js +365 -0
  188. package/dist/server/cable-test.js.map +1 -0
  189. package/dist/server/choices.js +51 -0
  190. package/dist/server/choices.js.map +1 -0
  191. package/dist/server/files.js +107 -0
  192. package/dist/server/files.js.map +1 -0
  193. package/dist/server/gate.js +128 -0
  194. package/dist/server/gate.js.map +1 -0
  195. package/dist/server/logs.js +76 -0
  196. package/dist/server/logs.js.map +1 -0
  197. package/dist/server/mobile.js +113 -0
  198. package/dist/server/mobile.js.map +1 -0
  199. package/dist/server/routes.js +326 -0
  200. package/dist/server/routes.js.map +1 -0
  201. package/dist/server/runs.js +111 -0
  202. package/dist/server/runs.js.map +1 -0
  203. package/dist/server/sanitize.js +242 -0
  204. package/dist/server/sanitize.js.map +1 -0
  205. package/dist/server/secrets.js +111 -0
  206. package/dist/server/secrets.js.map +1 -0
  207. package/dist/server/status.js +321 -0
  208. package/dist/server/status.js.map +1 -0
  209. package/dist/server/token.js +38 -0
  210. package/dist/server/token.js.map +1 -0
  211. package/dist/server/waiting.js +79 -0
  212. package/dist/server/waiting.js.map +1 -0
  213. package/dist/status-watch.mjs +63 -0
  214. package/dist/status-watch.mjs.map +1 -0
  215. package/package.json +74 -4
  216. package/skills/koppler-run/SKILL.md +169 -0
  217. package/skills/koppler-run/VERSION +1 -0
  218. package/skills/koppler-run/references/action-log.md +50 -0
  219. package/skills/koppler-run/references/permissions.md +25 -0
  220. package/skills/koppler-run/references/preparing-nodes.md +62 -0
  221. package/skills/koppler-run/references/reporting-bugs.md +76 -0
  222. package/skills/koppler-run/references/research.md +40 -0
  223. package/skills/koppler-run/references/secrets.md +56 -0
  224. package/skills/koppler-run/references/stack.md +197 -0
  225. package/skills/koppler-run/references/status.md +92 -0
@@ -0,0 +1,393 @@
1
+ // Reads Terraform and SAM config text: what each module declares per environment (addresses, settings, secret names,
2
+ // calls and queues). Only names and plain addresses are read out, never other values.
3
+ export const ENV_TOKEN = /(?:^|[-_./])(dev|development|qa|test|uat|staging|stage|prod|production|prd|live)(?=[-_./]|$)/i;
4
+ const SYNONYMS = {
5
+ prod: ['production', 'prd', 'live'],
6
+ staging: ['stage'],
7
+ dev: ['development'],
8
+ };
9
+ const HOST = /^(?=.{4,253}$)([a-z0-9-]+\.)+[a-z]{2,}$/i;
10
+ const SECRETISH = /secret|password|passwd|token|api_?key|private|credential|connectionstring/i;
11
+ // Settings and parameters of AWS's own tooling, which say nothing about the app.
12
+ const TOOLING = /^(PARAMETERS_SECRETS_EXTENSION|SECRETS_MANAGER_TTL|AWS_|POWERTOOLS_|\/aws\/)/;
13
+ export const tokenIn = (name) => ENV_TOKEN.exec(name ?? '')?.[1]?.toLowerCase();
14
+ /**
15
+ * Terraform text of the same length and lines, with what is inside quotes turned into "_" and comments into spaces, so
16
+ * that braces, brackets and comment marks can be counted without mistaking text for code.
17
+ */
18
+ // ponytail: heredocs (<<EOF) are read as code; mask them too if a policy written that way is ever misread
19
+ function masked(text) {
20
+ let out = '';
21
+ // What the reader is inside of: a quoted text, or an interpolation with its count of open braces.
22
+ const inside = [];
23
+ for (let at = 0; at < text.length; at++) {
24
+ const char = text[at] ?? '';
25
+ const two = text.slice(at, at + 2);
26
+ const top = inside.at(-1);
27
+ const hide = (count, fill) => {
28
+ const part = text.slice(at, at + count);
29
+ at += count - 1;
30
+ return part.replace(/[^\n]/g, fill);
31
+ };
32
+ const rest = (end, tail) => (end < 0 ? text.length : end + tail) - at;
33
+ if (top === 'text') {
34
+ if (char === '\\')
35
+ out += hide(2, '_');
36
+ else if (char === '"') {
37
+ inside.pop();
38
+ out += char;
39
+ }
40
+ else if (two === '${') {
41
+ inside.push(0);
42
+ out += hide(2, '_');
43
+ }
44
+ else
45
+ out += hide(1, '_');
46
+ }
47
+ else if (char === '"') {
48
+ inside.push('text');
49
+ out += typeof top === 'number' ? '_' : char;
50
+ }
51
+ else if (typeof top === 'number') {
52
+ if (char === '{')
53
+ inside[inside.length - 1] = top + 1;
54
+ else if (char === '}') {
55
+ if (top === 0)
56
+ inside.pop();
57
+ else
58
+ inside[inside.length - 1] = top - 1;
59
+ }
60
+ out += hide(1, '_');
61
+ }
62
+ else if (char === '#' || two === '//')
63
+ out += hide(rest(text.indexOf('\n', at), 0), ' ');
64
+ else if (two === '/*')
65
+ out += hide(rest(text.indexOf('*/', at + 2), 2), ' ');
66
+ else
67
+ out += char;
68
+ }
69
+ return out;
70
+ }
71
+ /** The body between the braces that follow each match of `head`. */
72
+ export function blocks(text, head) {
73
+ const out = [];
74
+ const code = masked(text);
75
+ for (const match of text.matchAll(head)) {
76
+ // Named inside a comment or a quoted text, it is not a block.
77
+ if (code[match.index] !== text[match.index])
78
+ continue;
79
+ const open = code.indexOf('{', match.index + match[0].length - 1);
80
+ if (open < 0)
81
+ continue;
82
+ let depth = 0;
83
+ let at = open;
84
+ for (; at < code.length; at++) {
85
+ if (code[at] === '{')
86
+ depth++;
87
+ else if (code[at] === '}' && !--depth)
88
+ break;
89
+ }
90
+ out.push({ match, body: text.slice(open + 1, at) });
91
+ }
92
+ return out;
93
+ }
94
+ const opened = (code) => (code.match(/[{[(]/g) ?? []).length - (code.match(/[}\])]/g) ?? []).length;
95
+ /** `key = value` pairs written directly in a block, with a nested map or list kept whole. */
96
+ export function assignments(body) {
97
+ const out = [];
98
+ const code = masked(body).split('\n');
99
+ const lines = body.split('\n').map((line, at) => line.slice(0, (code[at] ?? '').trimEnd().length));
100
+ for (let at = 0, depth = 0; at < lines.length; at++) {
101
+ const [, key, start] = (depth === 0 && /^\s*"?([\w.-]+)"?\s*=\s*(.*)$/.exec(lines[at] ?? '')) || [];
102
+ if (key === undefined) {
103
+ depth += opened(code[at] ?? '');
104
+ continue;
105
+ }
106
+ let value = start ?? '';
107
+ let open = opened(code[at] ?? '');
108
+ while (open > 0 && ++at < lines.length) {
109
+ value += '\n' + (lines[at] ?? '');
110
+ open += opened(code[at] ?? '');
111
+ }
112
+ out.push([key, value.trim().replace(/,$/, '')]);
113
+ }
114
+ return out;
115
+ }
116
+ const assigned = (body, key) => assignments(body).find(([name]) => name === key)?.[1];
117
+ /** Works out a Terraform expression from variables, locals and the workspace; null when it cannot be told. */
118
+ export function resolve(raw, context, depth = 0) {
119
+ if (raw == null || depth > 12)
120
+ return null;
121
+ const again = (next) => resolve(next, context, depth + 1);
122
+ const value = raw.trim();
123
+ if (/^"[^"]*"$/.test(value) || /^"(?:[^"\\]|\\.|\$\{[^}]*\})*"$/.test(value)) {
124
+ let unknown = 0;
125
+ const text = value.slice(1, -1).replace(/\$\{([^}]+)\}/g, (_, reference) => {
126
+ const part = again(reference);
127
+ if (typeof part === 'string')
128
+ return part;
129
+ unknown++;
130
+ return '';
131
+ });
132
+ return unknown ? null : text;
133
+ }
134
+ if (value.startsWith('{'))
135
+ return Object.fromEntries(assignments(value.slice(1, value.lastIndexOf('}'))));
136
+ if (value === 'terraform.workspace')
137
+ return context.workspace ?? null;
138
+ const either = /^([\w.[\]]+)\s*==\s*"([^"]*)"\s*\?\s*(.+?)\s+:\s+(.+)$/s.exec(value);
139
+ if (either) {
140
+ const left = again(either[1]);
141
+ return typeof left === 'string' ? again(left === either[2] ? either[3] : either[4]) : null;
142
+ }
143
+ const index = /^(.+)\[([^[\]]+)\]$/.exec(value);
144
+ if (index) {
145
+ const map = again(index[1]);
146
+ const key = again(index[2]);
147
+ return map && typeof map === 'object' && typeof key === 'string' ? again(map[key]) : null;
148
+ }
149
+ const reference = /^(var|local)\.([\w-]+)$/.exec(value);
150
+ if (reference)
151
+ return again((reference[1] === 'var' ? context.vars : context.locals)[reference[2] ?? '']);
152
+ return null;
153
+ }
154
+ const named = (raw, context) => {
155
+ const name = resolve(raw, context);
156
+ return typeof name === 'string' ? name : null;
157
+ };
158
+ /** An address safe to show: a host, or an http(s) URL with no credentials, no query and no path that could be a token. */
159
+ export function addressOf(value) {
160
+ if (typeof value !== 'string')
161
+ return null;
162
+ if (HOST.test(value))
163
+ return value.toLowerCase();
164
+ try {
165
+ const url = new URL(value);
166
+ if (!/^https?:$/.test(url.protocol) || url.username || url.password || url.search || !HOST.test(url.hostname))
167
+ return null;
168
+ // A path is kept only when it reads as a plain API prefix (/api/v1); anything else may be a token (a webhook URL).
169
+ const segments = url.pathname.split('/').filter(Boolean);
170
+ const plain = segments.length <= 3 && segments.every(segment => /^[a-z][a-z0-9-]{0,19}$/.test(segment));
171
+ return plain ? `${url.origin}${url.pathname.replace(/\/$/, '')}` : url.origin;
172
+ }
173
+ catch {
174
+ return null;
175
+ }
176
+ }
177
+ /** The smallest {...} around position `at` in `text`. */
178
+ function around(text, at) {
179
+ let start = at;
180
+ let depth = 0;
181
+ for (; start >= 0; start--) {
182
+ if (text[start] === '}')
183
+ depth++;
184
+ else if (text[start] === '{' && !depth--)
185
+ break;
186
+ }
187
+ let end = at;
188
+ depth = 0;
189
+ for (; end < text.length; end++) {
190
+ if (text[end] === '{')
191
+ depth++;
192
+ else if (text[end] === '}' && !depth--)
193
+ break;
194
+ }
195
+ return text.slice(Math.max(0, start), end + 1);
196
+ }
197
+ const DEAD_LETTER = /dlq|dead.?letter/i;
198
+ const FEEDERS = [
199
+ ['s3', 'S3 bucket notifications'],
200
+ ['events', 'an EventBridge rule'],
201
+ ['apigateway', 'an API Gateway route'],
202
+ ['sns', 'an SNS topic'],
203
+ ];
204
+ const resource = (types) => new RegExp(`(?:resource|data)\\s+"(${types})"\\s+"[\\w-]+"\\s*\\{`, 'g');
205
+ /** Settings a task definition gives its containers, as written. */
206
+ const taskSettings = (tf, value) => blocks(tf, resource('aws_ecs_task_definition')).flatMap(block => [...block.body.matchAll(new RegExp(`name\\s*[=:]\\s*"([\\w.]+)"\\s*,?\\s*value\\s*[=:]\\s*(${value})`, 'g'))].map((match) => [match[1] ?? '', match[2] ?? '']));
207
+ /**
208
+ * Queues and topics a Terraform folder declares or looks up, and how its app uses each: whether it reads or sends, the
209
+ * settings that carry the queue's address, and outside systems that feed it. Dead-letter queues are left out.
210
+ */
211
+ export function queueUses(tf) {
212
+ const found = new Map();
213
+ const add = (address, type, body) => {
214
+ if (DEAD_LETTER.test(address))
215
+ return;
216
+ const raw = assigned(body, 'name') ?? null;
217
+ found.set(address, { address, type, raw, reads: false, sends: false, env: new Set(), fedBy: new Set() });
218
+ };
219
+ for (const { match, body } of blocks(tf, /(resource|data)\s+"(aws_sqs_queue|aws_sns_topic)"\s+"([\w-]+)"\s*\{/g))
220
+ add(`${match[1] === 'data' ? 'data.' : ''}${match[2] ?? ''}.${match[3] ?? ''}`, match[2] === 'aws_sns_topic' ? 'sns' : 'sqs', body);
221
+ for (const { match, body } of blocks(tf, /module\s+"([\w-]+)"\s*\{/g)) {
222
+ const source = assigned(body, 'source') ?? '';
223
+ if (/\b(sqs|sns)\b/i.test(source))
224
+ add(`module.${match[1] ?? ''}`, /\bsns\b/i.test(source) ? 'sns' : 'sqs', body);
225
+ }
226
+ const refTo = (address) => new RegExp(`${address.replace(/\./g, '\\.')}(?:\\[[^\\]]*\\])?\\.(?:arn|url|id|name)\\b`, 'g');
227
+ for (const { match, body } of blocks(tf, /(?:resource|data)\s+"([\w-]+)"\s+"[\w-]+"\s*\{/g)) {
228
+ const type = match[1] ?? '';
229
+ for (const queue of found.values())
230
+ for (const use of body.matchAll(refTo(queue.address))) {
231
+ const near = around(body, use.index);
232
+ if (/^aws_(sqs_queue|sns_topic)_policy$/.test(type)) {
233
+ // The queue's own policy says which outside service may send to it.
234
+ for (const [service, what] of FEEDERS)
235
+ if (body.includes(`${service}.amazonaws.com`))
236
+ queue.fedBy.add(what);
237
+ }
238
+ else if (type === 'aws_lambda_event_source_mapping')
239
+ queue.reads = true;
240
+ else if (type === 'aws_s3_bucket_notification')
241
+ queue.fedBy.add('S3 bucket notifications');
242
+ else if (type === 'aws_cloudwatch_event_target')
243
+ queue.fedBy.add('an EventBridge rule');
244
+ else {
245
+ // One statement can allow both.
246
+ if (/sqs:SendMessage|sns:Publish|"sqs:\*"/.test(near))
247
+ queue.sends = true;
248
+ if (/sqs:ReceiveMessage|"sqs:\*"/.test(near))
249
+ queue.reads = true;
250
+ }
251
+ }
252
+ }
253
+ // Settings whose value is the queue's address: what a local run sets to the local queue.
254
+ const settings = [
255
+ ...blocks(tf, /resource\s+"aws_lambda_function"\s+"[\w-]+"\s*\{/g)
256
+ .flatMap(block => blocks(block.body, /variables\s*=\s*\{/g))
257
+ .flatMap(block => assignments(block.body)),
258
+ ...blocks(tf, /resource\s+"aws_ecs_task_definition"\s+"[\w-]+"\s*\{/g).flatMap(block => [...block.body.matchAll(/name\s*[=:]\s*"([\w.]+)"\s*,?\s*value\s*[=:]\s*([^\s,}]+)/g)].map((match) => [
259
+ match[1] ?? '',
260
+ match[2] ?? '',
261
+ ])),
262
+ ];
263
+ for (const queue of found.values())
264
+ for (const [name, raw] of settings)
265
+ if (refTo(queue.address).test(raw))
266
+ queue.env.add(name);
267
+ return [...found.values()].map(queue => ({ ...queue, env: [...queue.env].sort(), fedBy: [...queue.fedBy] }));
268
+ }
269
+ export const hostOf = (address) => {
270
+ try {
271
+ return new URL(address.includes('://') ? address : `https://${address}`).hostname;
272
+ }
273
+ catch {
274
+ return null;
275
+ }
276
+ };
277
+ /**
278
+ * One Terraform folder: what it declares, worked out once per environment. Environments come from its variable files'
279
+ * names; without those, each name in `workspaces` is tried as the Terraform workspace (and as an `environment` variable).
280
+ */
281
+ export function readModule(files, workspaces = []) {
282
+ const tf = files
283
+ .filter(file => file.name.endsWith('.tf'))
284
+ .map(file => file.text)
285
+ .join('\n');
286
+ const defaults = Object.fromEntries(blocks(tf, /variable\s+"([\w-]+)"\s*\{/g).flatMap(({ match, body }) => {
287
+ const value = assigned(body, 'default');
288
+ return value === undefined ? [] : [[match[1] ?? '', value]];
289
+ }));
290
+ const locals = Object.fromEntries(blocks(tf, /(^|\n)\s*locals\s*\{/g).flatMap(block => assignments(block.body)));
291
+ const varFiles = files
292
+ .filter(file => file.name.endsWith('.tfvars'))
293
+ .map(file => ({ token: tokenIn(file.name), vars: Object.fromEntries(assignments(file.text)) }));
294
+ const shared = varFiles.reduce((all, file) => (file.token ? all : { ...all, ...file.vars }), defaults);
295
+ const perEnv = varFiles.flatMap(file => (file.token ? [{ token: file.token, vars: file.vars }] : []));
296
+ const asVariables = (token) => Object.fromEntries(['environment', 'env', 'stage'].filter(key => !(key in shared)).map(key => [key, `"${token}"`]));
297
+ const contexts = perEnv.length
298
+ ? perEnv.map(file => ({ token: file.token, workspace: file.token, vars: { ...shared, ...file.vars }, locals }))
299
+ : workspaces.length
300
+ ? workspaces.map(token => ({ token, workspace: token, vars: { ...asVariables(token), ...shared }, locals }))
301
+ : [{ token: null, workspace: null, vars: shared, locals }];
302
+ const pick = (types, key) => blocks(tf, resource(types)).flatMap(block => assignments(block.body)
303
+ .filter(([name]) => name === key)
304
+ .map(([, raw]) => raw));
305
+ const listed = (raw) => raw.trim().startsWith('[')
306
+ ? raw
307
+ .replace(/^\[|\]$/g, '')
308
+ .split(',')
309
+ .map(item => item.trim())
310
+ .filter(Boolean)
311
+ : [raw];
312
+ const from = (source) => (raw) => ({ raw, from: source });
313
+ const declared = {
314
+ domains: [
315
+ ...pick('aws_api_gateway_domain_name|aws_apigatewayv2_domain_name', 'domain_name').map(from('api')),
316
+ ...pick('aws_cloudfront_distribution', 'aliases').flatMap(listed).map(from('cdn')),
317
+ ...pick('aws_route53_record', 'name').map(from('dns')),
318
+ ],
319
+ settings: [
320
+ ...blocks(tf, resource('aws_lambda_function'))
321
+ .flatMap(block => blocks(block.body, /environment\s*\{/g))
322
+ .flatMap(block => blocks(block.body, /variables\s*=\s*\{/g))
323
+ .flatMap(block => assignments(block.body)),
324
+ ...taskSettings(tf, '"[^"\\n]*"|[^\\s,}]+'),
325
+ ],
326
+ secrets: [
327
+ ...[...pick('aws_secretsmanager_secret', 'name'), ...pick('aws_secretsmanager_secret_version', 'secret_id')].map(raw => ({ raw, store: 'Secrets Manager' })),
328
+ ...pick('aws_ssm_parameter', 'name').map(raw => ({ raw, store: 'Parameter Store' })),
329
+ ],
330
+ };
331
+ const queues = queueUses(tf);
332
+ // Only a variable that names the account, with a value that reads as an id or a name: never a key or a token.
333
+ const accountOf = (context) => Object.entries(context.vars)
334
+ .filter(([key]) => /^(aws_)?account(_?(id|name|alias))?$/i.test(key))
335
+ .map(([, raw]) => named(raw, context))
336
+ .find(value => value !== null && /^[\w.-]{1,64}$/.test(value)) ?? null;
337
+ return contexts.map(context => ({
338
+ token: context.token,
339
+ queues: queues
340
+ .map(queue => ({ ...queue, name: named(queue.raw, context) }))
341
+ .filter(queue => !DEAD_LETTER.test(queue.name ?? '')),
342
+ account: accountOf(context),
343
+ domains: declared.domains.flatMap(({ raw, from: source }) => {
344
+ const host = addressOf(resolve(raw, context) ?? '');
345
+ return host && !host.includes('/') ? [{ host, from: source }] : [];
346
+ }),
347
+ settings: declared.settings
348
+ .filter(([name]) => !TOOLING.test(name))
349
+ .map(([name, raw]) => ({
350
+ name,
351
+ address: addressOf(resolve(raw, context)),
352
+ secret: SECRETISH.test(name) || /secret|sensitive/i.test(raw),
353
+ })),
354
+ // A name partly built at deploy time keeps its written form ("svc-${random}"); one that is all code is only counted.
355
+ secrets: declared.secrets
356
+ .map(({ raw, store }) => {
357
+ const written = raw.trim();
358
+ const name = named(raw, context) ?? (/^"[^"]*"$/.test(written) ? written.slice(1, -1) : null);
359
+ return { store, raw: written, name };
360
+ })
361
+ .filter(secret => !TOOLING.test(secret.name ?? '')),
362
+ }));
363
+ }
364
+ /** Which stack environment a Terraform environment name means: the same name, a common synonym, or one listed in the stack's envAliases. */
365
+ export function stackEnv(token, stack) {
366
+ if (!token)
367
+ return stack.envs.length === 1 ? (stack.envs[0] ?? null) : null;
368
+ const means = (env) => env === token || SYNONYMS[env]?.includes(token) || stack.envAliases?.[env]?.includes(token);
369
+ return stack.envs.find(means) ?? null;
370
+ }
371
+ /**
372
+ * The domains a SAM app deploys to, per samconfig.toml environment: its domain-like deploy parameters (HostedZoneName,
373
+ * DomainName, ...), the way Terraform's domain resources are read.
374
+ */
375
+ export function samDomains(toml) {
376
+ const out = [];
377
+ for (const section of toml.matchAll(/\[([\w-]+)\.deploy\.parameters\]([\s\S]*?)(?=\n\[|$)/g)) {
378
+ // One text or a list of them, in double or single quotes; a commented-out line is not read.
379
+ const overrides = /^[ \t]*parameter_overrides\s*=\s*(\[[\s\S]*?\]|"(?:[^"\\]|\\.)*"|'[^']*')/m.exec(section[2] ?? '');
380
+ const line = [...(overrides?.[1] ?? '').matchAll(/"((?:[^"\\]|\\.)*)"|'([^']*)'/g)]
381
+ .map(text => text[2] ?? (text[1] ?? '').replace(/\\(.)/g, '$1'))
382
+ .join(' ');
383
+ // Only parameters that name the app's own domain: a database or cache host is someone else's address.
384
+ const domains = [...line.matchAll(/(\w+)=(?:"([^"]*)"|(\S+))/g)].flatMap(([, key = '', quoted, bare]) => {
385
+ const value = quoted ?? bare ?? '';
386
+ const own = /(domain|hostedzone)(name)?$/i.test(key) && addressOf(value) && !value.includes('/');
387
+ return own ? [{ host: value.toLowerCase(), from: 'api' }] : [];
388
+ });
389
+ out.push({ token: (section[1] ?? '').toLowerCase(), domains });
390
+ }
391
+ return out.filter(section => section.domains.length);
392
+ }
393
+ //# sourceMappingURL=terraform.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terraform.js","sourceRoot":"","sources":["../../src/core/terraform.ts"],"names":[],"mappings":"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"}
package/dist/data.js ADDED
@@ -0,0 +1,37 @@
1
+ // The run files the engine, the server and the page share: the stack in use, the clones on this machine, the repos
2
+ // found, and the board. Each is one JSON file in the run folder.
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ import { resolveExpressions } from "./core/expressions.js";
6
+ import { readJson, writeJson } from "./json-files.js";
7
+ import { tempDir } from "./paths.js";
8
+ // Read at each call: the tests, and a stack switch, change where the run folder is while the process lives.
9
+ const folder = tempDir;
10
+ export const dataFile = (name) => path.join(folder(), `${name}.json`);
11
+ const isData = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
12
+ // Before JSON these were scripts for the page ("window.REGISTRY = {...};"). A board saved that way is still read, so
13
+ // nobody loses one; it is written back as JSON the next time it is saved.
14
+ // ponytail: drop once nobody can still have a state.js, i.e. after the first release
15
+ function readOldForm(name) {
16
+ try {
17
+ const text = fs.readFileSync(path.join(folder(), `${name}.js`), 'utf8');
18
+ return JSON.parse(text.slice(text.indexOf('{'), text.lastIndexOf('}') + 1));
19
+ }
20
+ catch {
21
+ return null;
22
+ }
23
+ }
24
+ /** One of the run files, or null when it is not there yet (before `koppler init`) or unreadable. */
25
+ export function readData(name) {
26
+ const value = readJson(dataFile(name)) ?? readOldForm(name);
27
+ return isData(value) ? value : null;
28
+ }
29
+ /** The stack in use, its expressions filled in. It passed the stack check when it was copied here, so it is read as one. */
30
+ export const readStack = () => resolveExpressions(readData('registry'));
31
+ /** The clones the last sync found, by app. */
32
+ export const readClones = () => (readData('local')?.['apps'] ?? {});
33
+ export function writeData(name, value) {
34
+ writeJson(dataFile(name), value);
35
+ fs.rmSync(path.join(folder(), `${name}.js`), { force: true });
36
+ }
37
+ //# sourceMappingURL=data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data.js","sourceRoot":"","sources":["../src/data.ts"],"names":[],"mappings":"AAAA,mHAAmH;AACnH,iEAAiE;AACjE,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE3D,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAKrC,4GAA4G;AAC5G,MAAM,MAAM,GAAG,OAAO,CAAC;AACvB,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAc,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,GAAG,IAAI,OAAO,CAAC,CAAC;AAEhF,MAAM,MAAM,GAAG,CAAC,KAAc,EAAiB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAEvH,qHAAqH;AACrH,0EAA0E;AAC1E,qFAAqF;AACrF,SAAS,WAAW,CAAC,IAAc;IACjC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,GAAG,IAAI,KAAK,CAAC,EAAE,MAAM,CAAC,CAAC;QACxE,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC9E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,oGAAoG;AACpG,MAAM,UAAU,QAAQ,CAAC,IAAc;IACrC,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC;IAC5D,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AACtC,CAAC;AAmBD,4HAA4H;AAC5H,MAAM,CAAC,MAAM,SAAS,GAAG,GAAG,EAAE,CAAC,kBAAkB,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAoB,CAAC;AAC3F,8CAA8C;AAC9C,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,EAAE,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAA6C,CAAC;AAEhH,MAAM,UAAU,SAAS,CAAC,IAAc,EAAE,KAAW;IACnD,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;IACjC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,GAAG,IAAI,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAChE,CAAC"}
@@ -0,0 +1,99 @@
1
+ // The action log: every temporary change Koppler or the agent made, which Stop undoes. A lost entry is a change Stop
2
+ // can never undo, so the log is written whole (a temporary file, then a rename), under a lock, and a log that cannot
3
+ // be read is never taken as empty: Koppler keeps a copy and stops, so a person can repair it first.
4
+ import fs from 'node:fs';
5
+ import path from 'node:path';
6
+ import { writeJson } from "../json-files.js";
7
+ const pause = (ms) => Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
8
+ const missing = (error, code) => error.code === code;
9
+ /** The log as a list; empty when there is none yet. Throws, keeping a copy, when it cannot be read as one. */
10
+ export function readActions(file) {
11
+ let text;
12
+ try {
13
+ text = fs.readFileSync(file, 'utf8');
14
+ }
15
+ catch (error) {
16
+ if (missing(error, 'ENOENT'))
17
+ return [];
18
+ throw error;
19
+ }
20
+ if (!text.trim())
21
+ return [];
22
+ let list = null;
23
+ try {
24
+ list = JSON.parse(text);
25
+ }
26
+ catch {
27
+ // Reported below, with the copy.
28
+ }
29
+ if (Array.isArray(list))
30
+ return list;
31
+ const copy = `${file}.damaged-${new Date().toISOString().replace(/[:.]/g, '-')}`;
32
+ try {
33
+ fs.copyFileSync(file, copy);
34
+ }
35
+ catch {
36
+ // The log itself is still there.
37
+ }
38
+ throw new Error(`the action log ${file} is damaged, so Stop could not undo what it lists. A copy is kept at ${copy}. Repair the log (it is a JSON list) or move it away, then try again; nothing else was changed`);
39
+ }
40
+ /**
41
+ * Reads the log, lets `change` edit it, and writes it back, with no other writer in between. Returns what `change`
42
+ * returned. A lock left by a process that died is taken over after 10 seconds.
43
+ */
44
+ export function updateActions(file, change) {
45
+ const lock = `${file}.lock`;
46
+ for (let waited = 0;; waited += 50) {
47
+ try {
48
+ fs.mkdirSync(lock);
49
+ break;
50
+ }
51
+ catch (error) {
52
+ if (!missing(error, 'EEXIST'))
53
+ throw error;
54
+ const age = Date.now() - (fs.statSync(lock, { throwIfNoEntry: false })?.mtimeMs ?? Date.now());
55
+ if (age > 10000) {
56
+ fs.rmSync(lock, { recursive: true, force: true });
57
+ continue;
58
+ }
59
+ if (waited > 10000)
60
+ throw new Error(`the action log ${file} is busy (another Koppler command is writing it); try again`, {
61
+ cause: error,
62
+ });
63
+ pause(50);
64
+ }
65
+ }
66
+ try {
67
+ const list = readActions(file);
68
+ const result = change(list);
69
+ writeJson(file, list);
70
+ return result;
71
+ }
72
+ finally {
73
+ fs.rmSync(lock, { recursive: true, force: true });
74
+ }
75
+ }
76
+ /**
77
+ * Writes a whole file Stop puts back: the text before the first write of the run is logged (null when there was no
78
+ * file, which Stop then takes away), and the text written last, so Stop leaves alone a file changed since.
79
+ */
80
+ export function writeLogged(logFile, app, file, text) {
81
+ let before = null;
82
+ try {
83
+ before = fs.readFileSync(file, 'utf8');
84
+ }
85
+ catch {
86
+ // No file yet.
87
+ }
88
+ const logged = (action) => action.kind === 'file' && action.file === file;
89
+ updateActions(logFile, list => {
90
+ const entry = list.find(logged);
91
+ if (entry)
92
+ entry.after = text;
93
+ else
94
+ list.push({ kind: 'file', app, file, before, after: text });
95
+ });
96
+ fs.mkdirSync(path.dirname(file), { recursive: true });
97
+ fs.writeFileSync(file, text, { mode: 0o600 });
98
+ }
99
+ //# sourceMappingURL=actions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions.js","sourceRoot":"","sources":["../../src/engine/actions.ts"],"names":[],"mappings":"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"}