@percher/shared 0.1.2 → 0.1.3

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.
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Valid app name: 3–40 chars, lowercase, starts with a letter,
3
+ * [a-z0-9-] only. App names become subdomains (name.percher.run),
4
+ * so changing this changes what hostnames the platform accepts.
5
+ */
6
+ export declare const APP_NAME_RE: RegExp;
7
+ //# sourceMappingURL=app-name.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-name.d.ts","sourceRoot":"","sources":["../src/app-name.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,WAAW,QAA2B,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Valid app name: 3–40 chars, lowercase, starts with a letter,
3
+ * [a-z0-9-] only. App names become subdomains (name.percher.run),
4
+ * so changing this changes what hostnames the platform accepts.
5
+ */
6
+ export const APP_NAME_RE = /^[a-z][a-z0-9-]{2,39}$/;
7
+ //# sourceMappingURL=app-name.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-name.js","sourceRoot":"","sources":["../src/app-name.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,wBAAwB,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,7 @@
1
+ export { APP_NAME_RE } from "./app-name";
2
+ export { MAX_TARBALL_BYTES } from "./limits";
1
3
  export { MAX_LOG_SEARCH_LENGTH } from "./logs";
4
+ export { canonicalInjectedKey, isPercherInjected, PERCHER_INJECTED_ENV_KEYS, } from "./platform-env";
2
5
  export { DEFAULT_NODE_VERSION_LABEL, DEFAULT_NODE_VERSION_MAJOR } from "./runtime";
3
6
  export { TIMEOUTS, type TimeoutKey } from "./timeouts";
4
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,QAAQ,CAAC;AAC/C,OAAO,EAAE,0BAA0B,EAAE,0BAA0B,EAAE,MAAM,WAAW,CAAC;AACnF,OAAO,EAAE,QAAQ,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,qBAAqB,EAAE,MAAM,QAAQ,CAAC;AAC/C,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,yBAAyB,GAC1B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,0BAA0B,EAAE,0BAA0B,EAAE,MAAM,WAAW,CAAC;AACnF,OAAO,EAAE,QAAQ,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,7 @@
1
+ export { APP_NAME_RE } from "./app-name";
2
+ export { MAX_TARBALL_BYTES } from "./limits";
1
3
  export { MAX_LOG_SEARCH_LENGTH } from "./logs";
4
+ export { canonicalInjectedKey, isPercherInjected, PERCHER_INJECTED_ENV_KEYS, } from "./platform-env";
2
5
  export { DEFAULT_NODE_VERSION_LABEL, DEFAULT_NODE_VERSION_MAJOR } from "./runtime";
3
6
  export { TIMEOUTS } from "./timeouts";
4
7
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,QAAQ,CAAC;AAC/C,OAAO,EAAE,0BAA0B,EAAE,0BAA0B,EAAE,MAAM,WAAW,CAAC;AACnF,OAAO,EAAE,QAAQ,EAAmB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,qBAAqB,EAAE,MAAM,QAAQ,CAAC;AAC/C,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,yBAAyB,GAC1B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,0BAA0B,EAAE,0BAA0B,EAAE,MAAM,WAAW,CAAC;AACnF,OAAO,EAAE,QAAQ,EAAmB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Max accepted compressed app-tarball size in bytes (500 MB). Enforced
3
+ * server-side on upload (Content-Length pre-check + streamed byte cap)
4
+ * and on GitHub/Forgejo repo imports; the CLI pre-checks before upload.
5
+ * Distinct from the decompressed extraction cap in the API's tarball
6
+ * extractor, which guards against zip bombs.
7
+ */
8
+ export declare const MAX_TARBALL_BYTES: number;
9
+ //# sourceMappingURL=limits.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../src/limits.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,QAAoB,CAAC"}
package/dist/limits.js ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Max accepted compressed app-tarball size in bytes (500 MB). Enforced
3
+ * server-side on upload (Content-Length pre-check + streamed byte cap)
4
+ * and on GitHub/Forgejo repo imports; the CLI pre-checks before upload.
5
+ * Distinct from the decompressed extraction cap in the API's tarball
6
+ * extractor, which guards against zip bombs.
7
+ */
8
+ export const MAX_TARBALL_BYTES = 500 * 1024 * 1024;
9
+ //# sourceMappingURL=limits.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limits.js","sourceRoot":"","sources":["../src/limits.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Env keys Percher injects into every user container at runtime. Treating
3
+ * these as "missing from your private settings" or "undeclared in
4
+ * percher.toml" produces false positives — the user can't (and shouldn't)
5
+ * set them; the platform does. Three consumers must stay locked together:
6
+ *
7
+ * - the source-scan classifier (apps/dashboard env-scan UI hides these)
8
+ * - the env gate (packages/api/src/pipeline/env-gate.ts auto-passes them)
9
+ * - the AI agent contract (docs/CLAUDE.md "Do NOT include" list)
10
+ *
11
+ * Pre-2026-05-29 each consumer kept its own list and they drifted — the
12
+ * env gate had {NODE_ENV, PORT, DATABASE_URL, POCKETBASE_*, PERCHER_APP_*}
13
+ * but the dashboard "Scan code" UI had nothing, so it surfaced every
14
+ * single one as "Referenced in code but missing from your private
15
+ * settings" and panicked users into setting bogus values.
16
+ *
17
+ * Keep this list in lockstep with docs/CLAUDE.md → "Do NOT include
18
+ * (Percher sets these automatically)" and the egress-proxy wiring
19
+ * documented under "Outbound HTTPS".
20
+ */
21
+ export declare const PERCHER_INJECTED_ENV_KEYS: ReadonlySet<string>;
22
+ /**
23
+ * True iff Percher injects this env key into every user container.
24
+ *
25
+ * Case-aware for proxy variants only — POSIX env vars are case-sensitive
26
+ * in general, but HTTP-proxy libraries by convention accept both cases.
27
+ * We do NOT case-fold arbitrary keys (PATH vs path are genuinely
28
+ * different envs to most software).
29
+ */
30
+ export declare function isPercherInjected(key: string): boolean;
31
+ /**
32
+ * Canonical (uppercase) form of an injected proxy variant, or the key
33
+ * unchanged. Used by the scan classifier to collapse `http_proxy` +
34
+ * `HTTP_PROXY` into a single entry.
35
+ */
36
+ export declare function canonicalInjectedKey(key: string): string;
37
+ //# sourceMappingURL=platform-env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-env.d.ts","sourceRoot":"","sources":["../src/platform-env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,yBAAyB,EAAE,WAAW,CAAC,MAAM,CAqBxD,CAAC;AAcH;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAItD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGxD"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Env keys Percher injects into every user container at runtime. Treating
3
+ * these as "missing from your private settings" or "undeclared in
4
+ * percher.toml" produces false positives — the user can't (and shouldn't)
5
+ * set them; the platform does. Three consumers must stay locked together:
6
+ *
7
+ * - the source-scan classifier (apps/dashboard env-scan UI hides these)
8
+ * - the env gate (packages/api/src/pipeline/env-gate.ts auto-passes them)
9
+ * - the AI agent contract (docs/CLAUDE.md "Do NOT include" list)
10
+ *
11
+ * Pre-2026-05-29 each consumer kept its own list and they drifted — the
12
+ * env gate had {NODE_ENV, PORT, DATABASE_URL, POCKETBASE_*, PERCHER_APP_*}
13
+ * but the dashboard "Scan code" UI had nothing, so it surfaced every
14
+ * single one as "Referenced in code but missing from your private
15
+ * settings" and panicked users into setting bogus values.
16
+ *
17
+ * Keep this list in lockstep with docs/CLAUDE.md → "Do NOT include
18
+ * (Percher sets these automatically)" and the egress-proxy wiring
19
+ * documented under "Outbound HTTPS".
20
+ */
21
+ export const PERCHER_INJECTED_ENV_KEYS = new Set([
22
+ // Container fundamentals
23
+ "NODE_ENV",
24
+ "PORT",
25
+ // Data backends (mode-specific but always one or the other; both safe
26
+ // to list — a key that's never set in the container still doesn't
27
+ // belong in the user's "private settings" UI)
28
+ "DATABASE_URL",
29
+ "POCKETBASE_URL",
30
+ "POCKETBASE_ADMIN_EMAIL",
31
+ "POCKETBASE_ADMIN_PASSWORD",
32
+ // App identity
33
+ "PERCHER_APP_NAME",
34
+ "PERCHER_APP_URL",
35
+ // Egress proxy (Percher injects these so app code can reach the
36
+ // public internet through the forward proxy — see docs/CLAUDE.md
37
+ // "Outbound HTTPS")
38
+ "HTTP_PROXY",
39
+ "HTTPS_PROXY",
40
+ "NO_PROXY",
41
+ "NODE_USE_ENV_PROXY",
42
+ ]);
43
+ /**
44
+ * Lowercase proxy variants that libraries (curl, requests, undici-via-
45
+ * NODE_USE_ENV_PROXY) accept interchangeably with the uppercase form.
46
+ * Treated as the same env at classification time so the scan UI doesn't
47
+ * show duplicate "missing" rows for `HTTP_PROXY` and `http_proxy`.
48
+ */
49
+ const PROXY_LOWERCASE_ALIASES = new Set([
50
+ "http_proxy",
51
+ "https_proxy",
52
+ "no_proxy",
53
+ ]);
54
+ /**
55
+ * True iff Percher injects this env key into every user container.
56
+ *
57
+ * Case-aware for proxy variants only — POSIX env vars are case-sensitive
58
+ * in general, but HTTP-proxy libraries by convention accept both cases.
59
+ * We do NOT case-fold arbitrary keys (PATH vs path are genuinely
60
+ * different envs to most software).
61
+ */
62
+ export function isPercherInjected(key) {
63
+ if (PERCHER_INJECTED_ENV_KEYS.has(key))
64
+ return true;
65
+ if (PROXY_LOWERCASE_ALIASES.has(key))
66
+ return true;
67
+ return false;
68
+ }
69
+ /**
70
+ * Canonical (uppercase) form of an injected proxy variant, or the key
71
+ * unchanged. Used by the scan classifier to collapse `http_proxy` +
72
+ * `HTTP_PROXY` into a single entry.
73
+ */
74
+ export function canonicalInjectedKey(key) {
75
+ if (PROXY_LOWERCASE_ALIASES.has(key))
76
+ return key.toUpperCase();
77
+ return key;
78
+ }
79
+ //# sourceMappingURL=platform-env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-env.js","sourceRoot":"","sources":["../src/platform-env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAwB,IAAI,GAAG,CAAS;IAC5E,yBAAyB;IACzB,UAAU;IACV,MAAM;IACN,sEAAsE;IACtE,kEAAkE;IAClE,8CAA8C;IAC9C,cAAc;IACd,gBAAgB;IAChB,wBAAwB;IACxB,2BAA2B;IAC3B,eAAe;IACf,kBAAkB;IAClB,iBAAiB;IACjB,gEAAgE;IAChE,iEAAiE;IACjE,oBAAoB;IACpB,YAAY;IACZ,aAAa;IACb,UAAU;IACV,oBAAoB;CACrB,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,uBAAuB,GAAwB,IAAI,GAAG,CAAS;IACnE,YAAY;IACZ,aAAa;IACb,UAAU;CACX,CAAC,CAAC;AAEH;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,IAAI,yBAAyB,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACpD,IAAI,uBAAuB,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAClD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAW;IAC9C,IAAI,uBAAuB,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC,WAAW,EAAE,CAAC;IAC/D,OAAO,GAAG,CAAC;AACb,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@percher/shared",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Shared constants and contracts (timeouts, etc.) used across the Percher CLI, API, MCP, and worker. Internal — values change in lockstep across packages.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -20,6 +20,11 @@
20
20
  "types": "./dist/runtime.d.ts",
21
21
  "import": "./dist/runtime.js",
22
22
  "default": "./dist/runtime.js"
23
+ },
24
+ "./platform-env": {
25
+ "types": "./dist/platform-env.d.ts",
26
+ "import": "./dist/platform-env.js",
27
+ "default": "./dist/platform-env.js"
23
28
  }
24
29
  },
25
30
  "files": [