cursedops 0.10.0 → 0.10.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cursedops",
3
- "version": "0.10.0",
3
+ "version": "0.10.2",
4
4
  "description": "The build-and-ops answers this generation's apps wrote independently and identically: finding a generation's roots — and printing a command that runs when pasted — without knowing a path, the generation's whole-tree laws run over one repo from a checkout or a worktree, macOS launchd agent install/replace/remove and the live port a job serves, the scaffolding and verdicts of a deployed smoke (origin probe, the smoke's own environment, a network that lies about DNS, a settled version), the static-serving helpers eight apps copied — the path-traversal guard among them — the API floor that keeps an unmatched /api/... from ever being answered with the app shell, the commit and dirty flag a checkout-served process reports, the Cloudflare Worker deploy toolkit four apps copied (the deploy sequence, exact-set secrets over a pipe, origin-first rollback, the curl edge fetch, the row-for-row D1 import proof, the billed-CPU tail check around a deploy's walk and smoke, and each app's worker:secrets and worker:smoke main as one function of its data), the relay a Worker fronts a Mac-bound app with (the Durable Object, the frames, the Mac's dialer and key rotation — lifted from station for roms), the Worker import-graph and await-port checks every Worker app's suite runs over its own source, and the public-surface ratchet three published libraries each carried a forked copy of. Mechanism only — no app knows its name from here. Bun, zero runtime dependencies (typescript is an optional peer, for public-surface only), ships source.",
5
5
  "type": "module",
6
6
  "scripts": {
package/src/relay.ts CHANGED
@@ -426,7 +426,10 @@ export class RelayLink {
426
426
  if (declared > this.maxBodyBytes) return tooBig();
427
427
  const id = crypto.randomUUID();
428
428
  const frame = await requestFrame(id, request);
429
- if (frame.body !== null && frame.body.length > (this.maxBodyBytes * 4) / 3 + 4) return tooBig();
429
+ // Exactly, off the base64: a chunked upload carries no content-length, and a slack bound let
430
+ // the ceiling + 2 bytes through (roms' suite caught it at MAX_BODY_BYTES + 1).
431
+ const pad = frame.body?.endsWith("==") ? 2 : frame.body?.endsWith("=") ? 1 : 0;
432
+ if (frame.body !== null && (frame.body.length / 4) * 3 - pad > this.maxBodyBytes) return tooBig();
430
433
  return await new Promise<Response>((resolve) => {
431
434
  const timer = setTimeout(() => {
432
435
  this.pending.delete(id);
package/src/relayLink.ts CHANGED
@@ -24,18 +24,37 @@ export interface LinkSettings {
24
24
  key: string;
25
25
  }
26
26
 
27
+ /**
28
+ * The link's three names, spelled WHOLE by the app — the env file's URL and key, and the Worker
29
+ * secret holding the key's digest. 🔴 Whole, not a prefix this module glues together: the app is
30
+ * then the visible reader of its own secrets, which is what `tools/check-secret-readers.ts` looks
31
+ * for (a built name like `` `${prefix}_LINK_URL` `` is invisible to it, and station's two keys read
32
+ * as "read by nothing" the day this module first took a prefix). A bare prefix string still works.
33
+ */
34
+ export interface LinkNames {
35
+ url: string;
36
+ key: string;
37
+ digest: string;
38
+ }
39
+
40
+ /** `"ROMS"` → `ROMS_LINK_URL` / `ROMS_LINK_KEY` / `ROMS_LINK_KEY_SHA256`; names pass through. */
41
+ export function linkNames(names: string | LinkNames): LinkNames {
42
+ return typeof names === "string" ? { url: `${names}_LINK_URL`, key: `${names}_LINK_KEY`, digest: `${names}_LINK_KEY_SHA256` } : names;
43
+ }
44
+
27
45
  /**
28
46
  * The link's URL and key out of its 0600 env file (`<APP>_LINK_URL`, `<APP>_LINK_KEY`), or a sentence
29
47
  * saying what is wrong. `wss://<host>/link`, or `ws://127.0.0.1:<port>/link` for a local workerd.
30
48
  */
31
- export function readLinkSettings(text: string, prefix: string, mintCommand = "bun run link:key"): LinkSettings | string {
49
+ export function readLinkSettings(text: string, names: string | LinkNames, mintCommand = "bun run link:key"): LinkSettings | string {
50
+ const n = linkNames(names);
32
51
  const found = readEnvFile(text);
33
- const url = found[`${prefix}_LINK_URL`]?.trim() ?? "";
34
- const key = found[`${prefix}_LINK_KEY`]?.trim() ?? "";
52
+ const url = found[n.url]?.trim() ?? "";
53
+ const key = found[n.key]?.trim() ?? "";
35
54
  if (!/^wss:\/\/[^/]+\/link$/.test(url) && !/^ws:\/\/(127\.0\.0\.1|localhost)(:\d+)?\/link$/.test(url)) {
36
- return `${prefix}_LINK_URL must be wss://<host>/link (or ws://127.0.0.1:<port>/link for a local workerd), got "${url}"`;
55
+ return `${n.url} must be wss://<host>/link (or ws://127.0.0.1:<port>/link for a local workerd), got "${url}"`;
37
56
  }
38
- if (key.length < 32) return `${prefix}_LINK_KEY is missing or short — \`${mintCommand}\` mints one`;
57
+ if (key.length < 32) return `${n.key} is missing or short — \`${mintCommand}\` mints one`;
39
58
  return { url, key };
40
59
  }
41
60
 
@@ -159,8 +178,9 @@ export function mintLinkKey(): string {
159
178
  }
160
179
 
161
180
  /** The link's env file, single-quoted so a shell `source` cannot mangle it. */
162
- export function linkEnvText(prefix: string, url: string, key: string, mintCommand = "bun run link:key"): string {
163
- return `# ${prefix.toLowerCase()}'s link — written by \`${mintCommand}\`. The key never leaves this Mac.\n${prefix}_LINK_URL='${url}'\n${prefix}_LINK_KEY='${key}'\n`;
181
+ export function linkEnvText(names: string | LinkNames, url: string, key: string, mintCommand = "bun run link:key"): string {
182
+ const n = linkNames(names);
183
+ return `# the link — written by \`${mintCommand}\`. The key never leaves this Mac.\n${n.url}='${url}'\n${n.key}='${key}'\n`;
164
184
  }
165
185
 
166
186
  export interface RotateSpec {
@@ -168,8 +188,8 @@ export interface RotateSpec {
168
188
  appDir: string;
169
189
  /** The 0600 env file the Mac reads. */
170
190
  file: string;
171
- /** `ROMS` → `ROMS_LINK_URL` / `ROMS_LINK_KEY` / `ROMS_LINK_KEY_SHA256`. */
172
- prefix: string;
191
+ /** The three names ({@link LinkNames}) — or a prefix, `ROMS` → `ROMS_LINK_URL` / `ROMS_LINK_KEY` / `ROMS_LINK_KEY_SHA256`. */
192
+ names: string | LinkNames;
173
193
  /** A new URL, or undefined to keep the file's. */
174
194
  url?: string;
175
195
  /** `cloudflareCredential(...)` — the env overlay wrangler runs with. */
@@ -187,10 +207,11 @@ export interface RotateSpec {
187
207
  */
188
208
  export async function rotateLinkKey(spec: RotateSpec): Promise<{ ok: true; file: string } | { ok: false; why: string }> {
189
209
  const previous = existsSync(spec.file) ? readEnvFile(readFileSync(spec.file, "utf8")) : {};
190
- const url = spec.url ?? previous[`${spec.prefix}_LINK_URL`];
210
+ const n = linkNames(spec.names);
211
+ const url = spec.url ?? previous[n.url];
191
212
  if (!url) return { ok: false, why: `no link URL yet — pass \`--url wss://<worker host>/link\` the first time` };
192
213
  const key = mintLinkKey();
193
- const secret = `${spec.prefix}_LINK_KEY_SHA256`;
214
+ const secret = n.digest;
194
215
  const put =
195
216
  spec.putSecret ??
196
217
  ((name: string, value: string) => {
@@ -204,7 +225,7 @@ export async function rotateLinkKey(spec: RotateSpec): Promise<{ ok: true; file:
204
225
  });
205
226
  const done = put(secret, await sha256Hex(key));
206
227
  if (!done.ok) return { ok: false, why: `the Worker refused the digest — nothing was changed on this Mac:\n${done.detail}` };
207
- writeFileSync(spec.file, linkEnvText(spec.prefix, url, key), { mode: 0o600 });
228
+ writeFileSync(spec.file, linkEnvText(n, url, key), { mode: 0o600 });
208
229
  chmodSync(spec.file, 0o600);
209
230
  return { ok: true, file: spec.file };
210
231
  }