@elaraai/tsserver-plugin-east 1.0.35 → 1.0.37

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 (2) hide show
  1. package/dist/index.cjs +104 -1
  2. package/package.json +3 -3
package/dist/index.cjs CHANGED
@@ -919,6 +919,16 @@ function resolvesToFsImport(id, ctx) {
919
919
  const imp = importOfSymbol(ctx.checker.getSymbolAtLocation(id), t);
920
920
  return imp !== void 0 && t.isStringLiteral(imp.moduleSpecifier) && FS_MODULES.has(imp.moduleSpecifier.text);
921
921
  }
922
+ function insidePlatformImplement(node, t) {
923
+ let cur = node.parent;
924
+ while (cur !== void 0) {
925
+ if (t.isCallExpression(cur) && t.isPropertyAccessExpression(cur.expression) && cur.expression.name.text === "implement") {
926
+ return true;
927
+ }
928
+ cur = cur.parent;
929
+ }
930
+ return false;
931
+ }
922
932
  function isProcessEnv(node, t) {
923
933
  return t.isPropertyAccessExpression(node) && t.isIdentifier(node.expression) && node.expression.text === "process" && node.name.text === "env";
924
934
  }
@@ -941,6 +951,8 @@ var noCompileTimeDataInjection = {
941
951
  }
942
952
  if (insideBlockScope(node, ctx))
943
953
  return;
954
+ if (insidePlatformImplement(node, t))
955
+ return;
944
956
  if (isProcessEnv(node, t)) {
945
957
  fire(ctx, node, "Reading `process.env` at module scope couples the deployed program to its build environment. Make it an `e3.input` / dataset parameter.");
946
958
  return;
@@ -2083,6 +2095,95 @@ var noDuplicateDefinitionName = {
2083
2095
  }
2084
2096
  };
2085
2097
 
2098
+ // ../east-diagnostics/dist/src/rules/no-inline-credentials.js
2099
+ var NAME27 = "no-inline-credentials";
2100
+ var CODE27 = 990032;
2101
+ var CREDENTIAL_FIELDS = /* @__PURE__ */ new Set([
2102
+ "password",
2103
+ "passphrase",
2104
+ "privateKey",
2105
+ "secretAccessKey",
2106
+ "accessKeyId",
2107
+ "apiKey",
2108
+ "token",
2109
+ "accessToken",
2110
+ "refreshToken",
2111
+ "sessionToken",
2112
+ "secretKey",
2113
+ "clientSecret"
2114
+ ]);
2115
+ var HOST_FIELDS = /* @__PURE__ */ new Set(["host", "hostname", "endpoint", "url", "server", "address"]);
2116
+ var LOCAL_HOSTS = ["localhost", "127.0.0.1", "::1"];
2117
+ function isStringy(node, t) {
2118
+ return t.isStringLiteral(node) || t.isNoSubstitutionTemplateLiteral(node);
2119
+ }
2120
+ function literalCredential(init2, t) {
2121
+ if (isStringy(init2, t) && init2.text.length > 0)
2122
+ return init2;
2123
+ if (!t.isCallExpression(init2))
2124
+ return void 0;
2125
+ const callee = init2.expression;
2126
+ const calleeName = t.isIdentifier(callee) ? callee.text : t.isPropertyAccessExpression(callee) ? callee.name.text : void 0;
2127
+ if (calleeName !== "some" && calleeName !== "variant")
2128
+ return void 0;
2129
+ const args = calleeName === "variant" ? init2.arguments.slice(1) : init2.arguments;
2130
+ for (const arg of args) {
2131
+ if (isStringy(arg, t) && arg.text.length > 0)
2132
+ return arg;
2133
+ }
2134
+ return void 0;
2135
+ }
2136
+ function mentionsLocalHost(node, t) {
2137
+ if (isStringy(node, t) && LOCAL_HOSTS.some((h) => node.text.includes(h)))
2138
+ return true;
2139
+ let found = false;
2140
+ t.forEachChild(node, (child) => {
2141
+ if (!found && mentionsLocalHost(child, t))
2142
+ found = true;
2143
+ });
2144
+ return found;
2145
+ }
2146
+ function targetsLocalHost(obj, t) {
2147
+ for (const prop of obj.properties) {
2148
+ if (!t.isPropertyAssignment(prop))
2149
+ continue;
2150
+ const name = t.isIdentifier(prop.name) || t.isStringLiteral(prop.name) ? prop.name.text : void 0;
2151
+ if (name !== void 0 && HOST_FIELDS.has(name) && mentionsLocalHost(prop.initializer, t))
2152
+ return true;
2153
+ }
2154
+ return false;
2155
+ }
2156
+ var noInlineCredentials = {
2157
+ name: NAME27,
2158
+ code: CODE27,
2159
+ description: "Flag literal string credentials (password, secretAccessKey, token, \u2026) in East/e3 source \u2014 use Env.get so the IR carries the variable name, not the secret.",
2160
+ check(node, ctx) {
2161
+ const t = ctx.ts;
2162
+ if (!t.isPropertyAssignment(node))
2163
+ return;
2164
+ const name = t.isIdentifier(node.name) || t.isStringLiteral(node.name) ? node.name.text : void 0;
2165
+ if (name === void 0 || !CREDENTIAL_FIELDS.has(name))
2166
+ return;
2167
+ if (!importsEastPackage(ctx.sourceFile, t))
2168
+ return;
2169
+ const literal = literalCredential(node.initializer, t);
2170
+ if (literal === void 0)
2171
+ return;
2172
+ if (t.isObjectLiteralExpression(node.parent) && targetsLocalHost(node.parent, t))
2173
+ return;
2174
+ const sf = ctx.sourceFile;
2175
+ const start = literal.getStart(sf);
2176
+ ctx.report({
2177
+ ruleName: NAME27,
2178
+ code: CODE27,
2179
+ start,
2180
+ length: literal.getEnd() - start,
2181
+ messageText: `Literal credential in \`${name}\` \u2014 East source compiles to content-addressed IR that is stored, exported, and replicated, so a secret here is effectively unredactable. Use \`Env.get("YOUR_VAR")\` (east-node-std) and supply the value per environment: your shell locally, the deployment's secret store in hosted runtimes.`,
2182
+ category: "warning"
2183
+ });
2184
+ }
2185
+ };
2186
+
2086
2187
  // ../east-diagnostics/dist/src/rules/index.js
2087
2188
  var allRules = [
2088
2189
  // East-side idiom hygiene (original set)
@@ -2115,7 +2216,9 @@ var allRules = [
2115
2216
  noHandrolledValueTypeMirror,
2116
2217
  noHostComparisonOnEastValues,
2117
2218
  requireExampleReturns,
2118
- noDuplicateDefinitionName
2219
+ noDuplicateDefinitionName,
2220
+ // secrets hygiene: IR is content-addressed and replicated — no literal creds
2221
+ noInlineCredentials
2119
2222
  ];
2120
2223
 
2121
2224
  // ../east-diagnostics/dist/src/run.js
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elaraai/tsserver-plugin-east",
3
- "version": "1.0.35",
3
+ "version": "1.0.37",
4
4
  "license": "AGPL-3.0-or-later",
5
5
  "description": "TypeScript language service plugin for East — East idiom diagnostics and localized East type-diff error messages as native editor squiggles.",
6
6
  "main": "dist/index.cjs",
@@ -32,8 +32,8 @@
32
32
  "devDependencies": {
33
33
  "esbuild": "^0.27.3",
34
34
  "typescript": "~5.9.2",
35
- "@elaraai/east": "1.0.35",
36
- "@elaraai/east-diagnostics": "1.0.35"
35
+ "@elaraai/east-diagnostics": "1.0.37",
36
+ "@elaraai/east": "1.0.37"
37
37
  },
38
38
  "scripts": {
39
39
  "build": "node scripts/build.mjs",