@descryy/runtime-environment-profile 0.4.6 → 0.4.7

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.
@@ -43,5 +43,6 @@ export declare class EncryptedFileCredentialStore implements CredentialStore {
43
43
  private entryPath;
44
44
  private loadOrCreateKey;
45
45
  private loadOrCreateKeyUncached;
46
+ private readKeyIfPresent;
46
47
  }
47
48
  //# sourceMappingURL=credential-store.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"credential-store.d.ts","sourceRoot":"","sources":["../src/credential-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAQH,MAAM,WAAW,eAAe;IAC9B,0FAA0F;IAC1F,KAAK,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,kGAAkG;IAClG,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACxD,mGAAmG;IACnG,MAAM,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9C;AAkBD;;;;;;;;;;GAUG;AACH,qBAAa,4BAA6B,YAAW,eAAe;IAClE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,UAAU,CAAgC;gBAEtC,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE;IAM7C,KAAK,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgB3D,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IA2BvD,MAAM,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWlD,OAAO,CAAC,SAAS;YAKH,eAAe;YAOf,uBAAuB;CAUtC"}
1
+ {"version":3,"file":"credential-store.d.ts","sourceRoot":"","sources":["../src/credential-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,MAAM,WAAW,eAAe;IAC9B,0FAA0F;IAC1F,KAAK,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,kGAAkG;IAClG,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACxD,mGAAmG;IACnG,MAAM,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9C;AAkBD;;;;;;;;;;GAUG;AACH,qBAAa,4BAA6B,YAAW,eAAe;IAClE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,UAAU,CAAgC;gBAEtC,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE;IAM7C,KAAK,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAc3D,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IA8BvD,MAAM,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWlD,OAAO,CAAC,SAAS;YAKH,eAAe;YAWf,uBAAuB;YAoBvB,gBAAgB;CAgB/B"}
@@ -11,8 +11,7 @@
11
11
  * `KeychainCredentialStore` is a drop-in swap.
12
12
  */
13
13
  import { randomBytes, createCipheriv, createDecipheriv, createHash } from "node:crypto";
14
- import { mkdir, readFile, writeFile, unlink, chmod } from "node:fs/promises";
15
- import { existsSync } from "node:fs";
14
+ import { mkdir, readFile, writeFile, unlink, chmod, rename, link } from "node:fs/promises";
16
15
  import { homedir } from "node:os";
17
16
  import { join } from "node:path";
18
17
  const ALGORITHM = "aes-256-gcm";
@@ -56,18 +55,21 @@ export class EncryptedFileCredentialStore {
56
55
  authTag: cipher.getAuthTag().toString("base64"),
57
56
  ciphertext: ciphertext.toString("base64"),
58
57
  };
59
- const path = this.entryPath(credentialRef);
60
- await writeFile(path, JSON.stringify(envelope), { mode: 0o600 });
61
- await chmod(path, 0o600);
58
+ await writeFileAtomically(this.entryPath(credentialRef), JSON.stringify(envelope));
62
59
  }
63
60
  async retrieve(credentialRef) {
64
61
  const path = this.entryPath(credentialRef);
65
- if (!existsSync(path)) {
66
- return null;
62
+ let raw;
63
+ try {
64
+ raw = await readFile(path, "utf8");
67
65
  }
66
+ catch (error) {
67
+ if (error.code === "ENOENT")
68
+ return null;
69
+ throw error;
70
+ }
71
+ const envelope = parseEnvelope(raw, credentialRef);
68
72
  const key = await this.loadOrCreateKey();
69
- const raw = await readFile(path, "utf8");
70
- const envelope = JSON.parse(raw);
71
73
  const authTag = Buffer.from(envelope.authTag, "base64");
72
74
  // Reject on length before setAuthTag/final(): anything but a full
73
75
  // 16-byte tag (truncated, or written by a pre-S-1 build) must fail
@@ -101,19 +103,85 @@ export class EncryptedFileCredentialStore {
101
103
  }
102
104
  async loadOrCreateKey() {
103
105
  if (this.keyPromise === null) {
104
- this.keyPromise = this.loadOrCreateKeyUncached();
106
+ const attempt = this.loadOrCreateKeyUncached();
107
+ this.keyPromise = attempt;
108
+ attempt.catch(() => {
109
+ if (this.keyPromise === attempt)
110
+ this.keyPromise = null;
111
+ });
105
112
  }
106
113
  return this.keyPromise;
107
114
  }
108
115
  async loadOrCreateKeyUncached() {
109
116
  await mkdir(this.baseDir, { recursive: true, mode: 0o700 });
110
- if (existsSync(this.keyPath)) {
111
- return readFile(this.keyPath);
117
+ for (let attempt = 0; attempt < KEY_PUBLISH_ATTEMPTS; attempt += 1) {
118
+ const existing = await this.readKeyIfPresent();
119
+ if (existing !== null)
120
+ return existing;
121
+ const key = randomBytes(KEY_BYTES);
122
+ const candidate = `${this.keyPath}.${String(process.pid)}.${randomBytes(6).toString("hex")}.tmp`;
123
+ await writeFile(candidate, key, { mode: 0o600, flag: "wx" });
124
+ try {
125
+ await link(candidate, this.keyPath);
126
+ return key;
127
+ }
128
+ catch (error) {
129
+ if (error.code !== "EEXIST")
130
+ throw error;
131
+ }
132
+ finally {
133
+ await unlink(candidate).catch(() => undefined);
134
+ }
135
+ }
136
+ throw new Error(`EncryptedFileCredentialStore: could not create or read ${this.keyPath} after ${String(KEY_PUBLISH_ATTEMPTS)} attempts`);
137
+ }
138
+ async readKeyIfPresent() {
139
+ let key;
140
+ try {
141
+ key = await readFile(this.keyPath);
142
+ }
143
+ catch (error) {
144
+ if (error.code === "ENOENT")
145
+ return null;
146
+ throw error;
147
+ }
148
+ if (key.length !== KEY_BYTES) {
149
+ throw new Error(`EncryptedFileCredentialStore: ${this.keyPath} is ${String(key.length)} bytes, expected exactly ${String(KEY_BYTES)}. ` +
150
+ "It was not replaced, because stored credentials may depend on it; restore it from a backup or remove it together with the entries directory.");
112
151
  }
113
- const key = randomBytes(KEY_BYTES);
114
- await writeFile(this.keyPath, key, { mode: 0o600 });
115
- await chmod(this.keyPath, 0o600);
116
152
  return key;
117
153
  }
118
154
  }
155
+ const KEY_PUBLISH_ATTEMPTS = 5;
156
+ async function writeFileAtomically(path, contents) {
157
+ const temporary = `${path}.${String(process.pid)}.${randomBytes(6).toString("hex")}.tmp`;
158
+ try {
159
+ await writeFile(temporary, contents, { mode: 0o600, flag: "wx" });
160
+ await chmod(temporary, 0o600);
161
+ await rename(temporary, path);
162
+ }
163
+ catch (error) {
164
+ await unlink(temporary).catch(() => undefined);
165
+ throw error;
166
+ }
167
+ }
168
+ function parseEnvelope(raw, credentialRef) {
169
+ let parsed;
170
+ try {
171
+ parsed = JSON.parse(raw);
172
+ }
173
+ catch {
174
+ throw new Error(`EncryptedFileCredentialStore: the stored entry for "${credentialRef}" is not valid JSON and cannot be read; delete and store it again`);
175
+ }
176
+ const candidate = parsed;
177
+ if (candidate === null ||
178
+ typeof candidate !== "object" ||
179
+ typeof candidate.iv !== "string" ||
180
+ typeof candidate.authTag !== "string" ||
181
+ typeof candidate.ciphertext !== "string" ||
182
+ Buffer.from(candidate.iv, "base64").length !== IV_BYTES) {
183
+ throw new Error(`EncryptedFileCredentialStore: the stored entry for "${credentialRef}" is not a well-formed envelope and cannot be read; delete and store it again`);
184
+ }
185
+ return { iv: candidate.iv, authTag: candidate.authTag, ciphertext: candidate.ciphertext };
186
+ }
119
187
  //# sourceMappingURL=credential-store.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"credential-store.js","sourceRoot":"","sources":["../src/credential-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"credential-store.js","sourceRoot":"","sources":["../src/credential-store.ts"],"names":[],"mappings":"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"}
package/dist/profile.d.ts CHANGED
@@ -45,18 +45,18 @@ export interface EnvironmentProfile {
45
45
  */
46
46
  readonly remoteLogSource?: RemoteLogSourceConfig | null;
47
47
  }
48
- export type ProfileValidationError = "EMPTY_NAME" | "EMPTY_CREDENTIAL_REF" | "INVALID_URL" | "INVALID_SAFETY_LEVEL" | "INVALID_MODE" | "REMOTE_LOG_SOURCE_NOT_ALLOWED_FOR_MODE";
48
+ export type ProfileValidationError = "EMPTY_NAME" | "EMPTY_CREDENTIAL_REF" | "INVALID_URL" | "URL_EMBEDS_CREDENTIALS" | "URL_TARGETS_LINK_LOCAL_ADDRESS" | "INVALID_SAFETY_LEVEL" | "INVALID_MODE" | "REMOTE_LOG_SOURCE_NOT_ALLOWED_FOR_MODE";
49
49
  /**
50
50
  * Structural validation only — doesn't reach `url` or verify the
51
51
  * credential exists (runtime concerns), so it can run while a setup form
52
52
  * is still being filled in.
53
53
  */
54
54
  export declare function validateProfile(input: {
55
- readonly name: string;
56
- readonly url: string;
57
- readonly safetyLevel: string;
58
- readonly credentialRef: string;
59
- readonly mode: string;
55
+ readonly name: unknown;
56
+ readonly url: unknown;
57
+ readonly safetyLevel: unknown;
58
+ readonly credentialRef: unknown;
59
+ readonly mode: unknown;
60
60
  readonly remoteLogSource?: RemoteLogSourceConfig | null;
61
61
  }): readonly ProfileValidationError[];
62
62
  /** Throws with every validation error joined, not just the first, so a setup form can show all problems at once. */
@@ -1 +1 @@
1
- {"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../src/profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AAEnF,0FAA0F;AAC1F,eAAO,MAAM,aAAa,2DAA4D,CAAC;AACvF,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD,8FAA8F;AAC9F,eAAO,MAAM,aAAa,mEAAoE,CAAC;AAC/F,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD,MAAM,WAAW,kBAAkB;IACjC,gGAAgG;IAChG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC;;;OAGG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,2HAA2H;IAC3H,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B;;;;;;;;;OASG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;CACzD;AAED,MAAM,MAAM,sBAAsB,GAC9B,YAAY,GACZ,sBAAsB,GACtB,aAAa,GACb,sBAAsB,GACtB,cAAc,GACd,wCAAwC,CAAC;AAE7C;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,eAAe,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;CACzD,GAAG,SAAS,sBAAsB,EAAE,CA2BpC;AAWD,oHAAoH;AACpH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,eAAe,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;CACzD,GAAG,kBAAkB,CAarB"}
1
+ {"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../src/profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AAEnF,0FAA0F;AAC1F,eAAO,MAAM,aAAa,2DAA4D,CAAC;AACvF,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD,8FAA8F;AAC9F,eAAO,MAAM,aAAa,mEAAoE,CAAC;AAC/F,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD,MAAM,WAAW,kBAAkB;IACjC,gGAAgG;IAChG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC;;;OAGG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,2HAA2H;IAC3H,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B;;;;;;;;;OASG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;CACzD;AAED,MAAM,MAAM,sBAAsB,GAC9B,YAAY,GACZ,sBAAsB,GACtB,aAAa,GACb,wBAAwB,GACxB,gCAAgC,GAChC,sBAAsB,GACtB,cAAc,GACd,wCAAwC,CAAC;AAE7C;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE;IACrC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,eAAe,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;CACzD,GAAG,SAAS,sBAAsB,EAAE,CAyBpC;AA+BD,oHAAoH;AACpH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,eAAe,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;CACzD,GAAG,kBAAkB,CAarB"}
package/dist/profile.js CHANGED
@@ -25,19 +25,17 @@ export const PROFILE_MODES = ["localBooted", "localAttached", "remote", "product
25
25
  */
26
26
  export function validateProfile(input) {
27
27
  const errors = [];
28
- if (input.name.trim().length === 0) {
28
+ if (typeof input.name !== "string" || input.name.trim().length === 0) {
29
29
  errors.push("EMPTY_NAME");
30
30
  }
31
- if (input.credentialRef.trim().length === 0) {
31
+ if (typeof input.credentialRef !== "string" || input.credentialRef.trim().length === 0) {
32
32
  errors.push("EMPTY_CREDENTIAL_REF");
33
33
  }
34
- if (!isParsableUrl(input.url)) {
35
- errors.push("INVALID_URL");
36
- }
37
- if (!SAFETY_LEVELS.includes(input.safetyLevel)) {
34
+ errors.push(...urlErrors(input.url, input.mode));
35
+ if (typeof input.safetyLevel !== "string" || !SAFETY_LEVELS.includes(input.safetyLevel)) {
38
36
  errors.push("INVALID_SAFETY_LEVEL");
39
37
  }
40
- if (!PROFILE_MODES.includes(input.mode)) {
38
+ if (typeof input.mode !== "string" || !PROFILE_MODES.includes(input.mode)) {
41
39
  errors.push("INVALID_MODE");
42
40
  }
43
41
  // Rejected rather than silently dropped -- caller learns it wouldn't be honored.
@@ -47,14 +45,40 @@ export function validateProfile(input) {
47
45
  }
48
46
  return errors;
49
47
  }
50
- function isParsableUrl(url) {
51
- try {
52
- void new URL(url);
48
+ const WEB_PROTOCOLS = ["http:", "https:"];
49
+ const LOCAL_MODES = ["localBooted", "localAttached"];
50
+ const METADATA_HOSTNAMES = ["metadata.google.internal", "metadata", "instance-data.ec2.internal"];
51
+ function isLinkLocalOrMetadataHost(hostname) {
52
+ const host = hostname.toLowerCase().replace(/^\[|\]$/g, "").replace(/\.$/, "");
53
+ if (METADATA_HOSTNAMES.includes(host))
54
+ return true;
55
+ if (/^169\.254\.\d{1,3}\.\d{1,3}$/.test(host))
56
+ return true;
57
+ if (/^fe[89ab][0-9a-f]:/.test(host))
58
+ return true;
59
+ if (/^::ffff:(a9fe:|169\.254\.)/.test(host))
53
60
  return true;
61
+ return host === "fd00:ec2::254";
62
+ }
63
+ function urlErrors(url, mode) {
64
+ if (typeof url !== "string")
65
+ return ["INVALID_URL"];
66
+ let parsed;
67
+ try {
68
+ parsed = new URL(url);
54
69
  }
55
70
  catch {
56
- return false;
71
+ return ["INVALID_URL"];
57
72
  }
73
+ if (!WEB_PROTOCOLS.includes(parsed.protocol))
74
+ return ["INVALID_URL"];
75
+ const errors = [];
76
+ if (parsed.username !== "" || parsed.password !== "")
77
+ errors.push("URL_EMBEDS_CREDENTIALS");
78
+ const isLocalMode = typeof mode === "string" && LOCAL_MODES.includes(mode);
79
+ if (!isLocalMode && isLinkLocalOrMetadataHost(parsed.hostname))
80
+ errors.push("URL_TARGETS_LINK_LOCAL_ADDRESS");
81
+ return errors;
58
82
  }
59
83
  /** Throws with every validation error joined, not just the first, so a setup form can show all problems at once. */
60
84
  export function createEnvironmentProfile(input) {
@@ -1 +1 @@
1
- {"version":3,"file":"profile.js","sourceRoot":"","sources":["../src/profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,0FAA0F;AAC1F,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,yBAAyB,CAAU,CAAC;AAGvF,8FAA8F;AAC9F,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,aAAa,EAAE,eAAe,EAAE,QAAQ,EAAE,YAAY,CAAU,CAAC;AAoC/F;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,KAO/B;IACC,MAAM,MAAM,GAA6B,EAAE,CAAC;IAE5C,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC5B,CAAC;IACD,IAAI,KAAK,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5C,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;IACtC,CAAC;IACD,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAC9B,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC7B,CAAC;IACD,IAAI,CAAE,aAAmC,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC;QACtE,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;IACtC,CAAC;IACD,IAAI,CAAE,aAAmC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/D,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC9B,CAAC;IACD,iFAAiF;IACjF,IACE,KAAK,CAAC,eAAe,IAAI,IAAI;QAC7B,CAAC,KAAK,CAAC,IAAI,KAAK,aAAa,IAAI,KAAK,CAAC,IAAI,KAAK,eAAe,CAAC,EAChE,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;IACxD,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,aAAa,CAAC,GAAW;IAChC,IAAI,CAAC;QACH,KAAK,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,oHAAoH;AACpH,MAAM,UAAU,wBAAwB,CAAC,KAOxC;IACC,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IACtC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,gCAAgC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvE,CAAC;IACD,OAAO;QACL,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE;QACvB,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,aAAa,EAAE,KAAK,CAAC,aAAa,CAAC,IAAI,EAAE;QACzC,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,eAAe,EAAE,KAAK,CAAC,eAAe,IAAI,IAAI;KAC/C,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"profile.js","sourceRoot":"","sources":["../src/profile.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"safety-gate.d.ts","sourceRoot":"","sources":["../src/safety-gate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEvD,eAAO,MAAM,cAAc,gDAAiD,CAAC;AAC7E,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D,MAAM,WAAW,cAAc;IAC7B,yFAAyF;IACzF,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;CAC/B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,cAAc,GAAG,YAAY,CAQhG"}
1
+ {"version":3,"file":"safety-gate.d.ts","sourceRoot":"","sources":["../src/safety-gate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEvD,eAAO,MAAM,cAAc,gDAAiD,CAAC;AAC7E,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D,MAAM,WAAW,cAAc;IAC7B,yFAAyF;IACzF,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;CAC/B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,cAAc,GAAG,YAAY,CAehG"}
@@ -19,12 +19,20 @@ export const GATE_DECISIONS = ["allow", "deny", "requiresApproval"];
19
19
  * DEC-270 requires the level be declared, not auto-upgraded.
20
20
  */
21
21
  export function evaluateAction(profile, action) {
22
- if (action.destructive) {
23
- return profile.safetyLevel === "destructiveWithApproval" ? "requiresApproval" : "deny";
22
+ const level = profile?.safetyLevel;
23
+ const write = action?.write;
24
+ const destructive = action?.destructive;
25
+ if (typeof write !== "boolean" || typeof destructive !== "boolean")
26
+ return "deny";
27
+ switch (level) {
28
+ case "readOnly":
29
+ return write || destructive ? "deny" : "allow";
30
+ case "write":
31
+ return destructive ? "deny" : "allow";
32
+ case "destructiveWithApproval":
33
+ return destructive ? "requiresApproval" : "allow";
34
+ default:
35
+ return "deny";
24
36
  }
25
- if (action.write) {
26
- return profile.safetyLevel === "readOnly" ? "deny" : "allow";
27
- }
28
- return "allow";
29
37
  }
30
38
  //# sourceMappingURL=safety-gate.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"safety-gate.js","sourceRoot":"","sources":["../src/safety-gate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,kBAAkB,CAAU,CAAC;AAc7E;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,cAAc,CAAC,OAA2B,EAAE,MAAsB;IAChF,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,OAAO,OAAO,CAAC,WAAW,KAAK,yBAAyB,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,MAAM,CAAC;IACzF,CAAC;IACD,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,OAAO,OAAO,CAAC,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;IAC/D,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
1
+ {"version":3,"file":"safety-gate.js","sourceRoot":"","sources":["../src/safety-gate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,kBAAkB,CAAU,CAAC;AAc7E;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,cAAc,CAAC,OAA2B,EAAE,MAAsB;IAChF,MAAM,KAAK,GAAY,OAAO,EAAE,WAAW,CAAC;IAC5C,MAAM,KAAK,GAAY,MAAM,EAAE,KAAK,CAAC;IACrC,MAAM,WAAW,GAAY,MAAM,EAAE,WAAW,CAAC;IACjD,IAAI,OAAO,KAAK,KAAK,SAAS,IAAI,OAAO,WAAW,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC;IAClF,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,UAAU;YACb,OAAO,KAAK,IAAI,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;QACjD,KAAK,OAAO;YACV,OAAO,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;QACxC,KAAK,yBAAyB;YAC5B,OAAO,WAAW,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,OAAO,CAAC;QACpD;YACE,OAAO,MAAM,CAAC;IAClB,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@descryy/runtime-environment-profile",
3
- "version": "0.4.6",
3
+ "version": "0.4.7",
4
4
  "type": "module",
5
5
  "description": "Environment profiles per DEC-270/DEC-266: a user-named target (local booted/attached, remote dev/staging/preview, production) carrying a declared safety level, scoped credentials, and the safety-gate enforcement point destructive actions must call before running.",
6
6
  "license": "UNLICENSED",
@@ -26,7 +26,7 @@
26
26
  "access": "public"
27
27
  },
28
28
  "dependencies": {
29
- "@descryy/runtime-remote-log-ingestion": "0.4.6"
29
+ "@descryy/runtime-remote-log-ingestion": "0.4.7"
30
30
  },
31
31
  "scripts": {
32
32
  "build": "tsc -b"