@launchfile/macos-dev 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/state.js CHANGED
@@ -4,10 +4,36 @@
4
4
  * Persists secrets, ports, and resource state in .launchfile/state.json
5
5
  * so credentials and ports are stable across restarts.
6
6
  */
7
- import { readFile, writeFile, mkdir } from "node:fs/promises";
7
+ import { readFile, writeFile, mkdir, chmod } from "node:fs/promises";
8
8
  import { join } from "node:path";
9
9
  import { createHash } from "node:crypto";
10
10
  import { registerSecrets } from "./redact.js";
11
+ /** The `db` use keys → index map `up` recorded on a resource: `db` from `dbIndex`, `db.<name>` from `namedDbIndexes`. */
12
+ export function recordedDbIndexes(res) {
13
+ const indexes = {};
14
+ if (res.dbIndex !== undefined)
15
+ indexes.db = res.dbIndex;
16
+ for (const [name, index] of Object.entries(res.namedDbIndexes ?? {})) {
17
+ indexes[`db.${name}`] = index;
18
+ }
19
+ return indexes;
20
+ }
21
+ /** `res` with the allocated `db` indexes recorded — the inverse of {@link recordedDbIndexes}. Records nothing for an empty allocation. */
22
+ export function withRecordedDbIndexes(res, indexes) {
23
+ const named = {};
24
+ let dbIndex;
25
+ for (const [key, index] of Object.entries(indexes)) {
26
+ if (key === "db")
27
+ dbIndex = index;
28
+ else
29
+ named[key.slice("db.".length)] = index;
30
+ }
31
+ return {
32
+ ...res,
33
+ ...(dbIndex !== undefined ? { dbIndex } : {}),
34
+ ...(Object.keys(named).length > 0 ? { namedDbIndexes: named } : {}),
35
+ };
36
+ }
11
37
  const STATE_DIR = ".launchfile";
12
38
  const STATE_FILE = "state.json";
13
39
  function stateDir(projectDir) {
@@ -64,8 +90,15 @@ export async function saveState(projectDir, state) {
64
90
  /** Ensure .launchfile directories exist */
65
91
  export async function ensureDirs(projectDir) {
66
92
  const dirs = ["storage", "tmp", "logs", "data", "env"];
67
- // Security: restrict permissions — these dirs contain secrets, logs, env files
68
- await Promise.all(dirs.map((d) => mkdir(join(projectDir, STATE_DIR, d), { recursive: true, mode: 0o700 })));
93
+ // Security: these dirs hold secrets, logs, and env files. mkdir applies the
94
+ // mode only when it creates the directory, so chmod unconditionally — a dir
95
+ // left by an earlier version or a looser umask must not stay world-readable
96
+ // (CWE-276). Mirrors packages/launchfile/src/state/errors.ts.
97
+ await Promise.all(dirs.map(async (d) => {
98
+ const dir = join(projectDir, STATE_DIR, d);
99
+ await mkdir(dir, { recursive: true, mode: 0o700 });
100
+ await chmod(dir, 0o700);
101
+ }));
69
102
  // Safety net: write a .gitignore inside .launchfile/ so secrets aren't
70
103
  // accidentally committed even if the project's .gitignore doesn't exclude it.
71
104
  await writeFile(join(projectDir, STATE_DIR, ".gitignore"), "*\n", { mode: 0o644 });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@launchfile/macos-dev",
3
- "version": "0.9.0",
3
+ "version": "0.11.0",
4
4
  "description": "macOS dev provider for Launchfile — run apps locally via brew services and native runtimes",
5
5
  "os": [
6
6
  "darwin"
@@ -36,7 +36,7 @@
36
36
  "directory": "providers/macos-dev"
37
37
  },
38
38
  "dependencies": {
39
- "@launchfile/sdk": "^0.9.0",
39
+ "@launchfile/sdk": "^0.11.0",
40
40
  "semver": "^7.7.4"
41
41
  },
42
42
  "devDependencies": {