@ttt-productions/repo-guards 0.1.17 → 0.1.19

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.
@@ -54,6 +54,7 @@ export interface AdminActionSurfaceFacts {
54
54
  adminCheckers: readonly string[];
55
55
  checkerReaders: readonly Reviewed[];
56
56
  adminDeclarations: CallableDeclarationFacts;
57
+ clientDeclarations: CallableDeclarationFacts;
57
58
  claimKeys: readonly string[];
58
59
  adminHooks: readonly string[];
59
60
  adminAreaRoots: readonly string[];
@@ -72,7 +73,7 @@ interface ClientAdminUse {
72
73
  symbol: string;
73
74
  detail: string;
74
75
  }
75
- export declare function clientAdminUses(file: FileView, facts: Pick<AdminActionSurfaceFacts, 'claimKeys' | 'adminHooks'>, declarationModuleOf: (spec: string) => string | null): ClientAdminUse[];
76
+ export declare function clientAdminUses(file: FileView, facts: Pick<AdminActionSurfaceFacts, 'claimKeys' | 'adminHooks'>, declarationModuleOf: (spec: string) => string | null, areaModuleOf?: (spec: string) => string | null): ClientAdminUse[];
76
77
  export declare const adminActionSurfaceGuard: GenericGuardDefinition<AdminActionSurfaceFacts>;
77
78
  export {};
78
79
  //# sourceMappingURL=auth.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/modules/backend/auth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/modules/backend/auth.ts"],"names":[],"mappings":"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"}
@@ -419,7 +419,7 @@ export function adminOnlyCallables(file, adminAuth) {
419
419
  })
420
420
  .map((callable) => callable.name);
421
421
  }
422
- export function clientAdminUses(file, facts, declarationModuleOf) {
422
+ export function clientAdminUses(file, facts, declarationModuleOf, areaModuleOf = () => null) {
423
423
  const out = [];
424
424
  const keys = new RegExp(`\\b(${facts.claimKeys.map(escapeRegExp).join('|')})\\b`);
425
425
  for (const hit of adminClaimMatcher(facts.claimKeys)(file))
@@ -442,6 +442,17 @@ export function clientAdminUses(file, facts, declarationModuleOf) {
442
442
  });
443
443
  continue;
444
444
  }
445
+ const area = site.typeOnly ? null : areaModuleOf(site.spec);
446
+ if (area) {
447
+ const names = site.named.filter((n) => !n.typeOnly).map((n) => n.imported);
448
+ for (const symbol of site.named.length ? names : ['*'])
449
+ out.push({
450
+ index,
451
+ symbol,
452
+ detail: `imports ${symbol} from the admin area ${area}`,
453
+ });
454
+ continue;
455
+ }
445
456
  for (const name of site.named)
446
457
  if (hooks.has(name.imported))
447
458
  out.push({
@@ -478,6 +489,7 @@ export const adminActionSurfaceGuard = {
478
489
  namesProblem(facts?.adminCheckers, 'adminCheckers', problems);
479
490
  reviewedProblems(facts?.checkerReaders, 'checkerReaders', problems);
480
491
  declarationFactProblems(facts?.adminDeclarations, 'adminDeclarations', problems);
492
+ declarationFactProblems(facts?.clientDeclarations, 'clientDeclarations', problems);
481
493
  namesProblem(facts?.claimKeys, 'claimKeys', problems);
482
494
  namesProblem(facts?.adminHooks, 'adminHooks', problems, { nonEmpty: false });
483
495
  adminAreaProblems(facts, problems);
@@ -494,10 +506,12 @@ export const adminActionSurfaceGuard = {
494
506
  description: `The admin-only callables are every callable whose ${facts.adminAuth.call} calls all carry ` +
495
507
  `${facts.adminAuth.option}, read from the Functions source each run. Inside a callable module, admin standing ` +
496
508
  `is checked only through that auth call: ${facts.adminCheckers.join(', ')} is called only by the reviewed ` +
497
- `readers. ${facts.adminDeclarations.modules.join(', ')} declares exactly the admin-only callables, no more and ` +
498
- `no fewer. Outside the admin area (${facts.adminAreaRoots.join(', ')}) and the admin-actions affordance ` +
499
- `(${facts.affordanceOwner}), client code never reads the admin claim, imports an admin declaration, or imports ` +
500
- 'an admin hook: an admin action there goes through the affordance, and any other admin-standing read is a ' +
509
+ `readers. ${facts.adminDeclarations.modules.join(', ')} declares only admin-only callables, and every admin-only ` +
510
+ `callable the client declares (${facts.clientDeclarations.modules.join(', ')}) is declared there; one with no ` +
511
+ `client declaration has no client caller. Outside the admin area (${facts.adminAreaRoots.join(', ')}) and the ` +
512
+ `admin-actions affordance (${facts.affordanceOwner}), client code never reads the admin claim, imports an admin ` +
513
+ 'declaration, imports a module of the admin area, or imports an admin hook: an admin action there goes through ' +
514
+ 'the affordance, and any other admin-standing read is a ' +
501
515
  'reviewed entry ({ path, symbol?, why }). A reviewed reader or entry that no longer matches is stale.',
502
516
  samples: {
503
517
  flags: [
@@ -554,6 +568,14 @@ export const adminActionSurfaceGuard = {
554
568
  });
555
569
  const { declared, findings: declarationFindings } = readDeclarations(context, facts.adminDeclarations);
556
570
  findings.push(...declarationFindings);
571
+ const clientRead = readDeclarations(context, {
572
+ ...facts.clientDeclarations,
573
+ modules: facts.clientDeclarations.modules.filter((m) => !declarationModules.has(m)),
574
+ });
575
+ findings.push(...clientRead.findings);
576
+ const clientDeclared = new Set([...declared, ...clientRead.declared]
577
+ .map((d) => d.callable)
578
+ .filter((c) => c !== null));
557
579
  const declaredNames = new Set();
558
580
  for (const d of declared) {
559
581
  if (d.callable === null)
@@ -567,10 +589,10 @@ export const adminActionSurfaceGuard = {
567
589
  });
568
590
  }
569
591
  for (const [name, where] of adminCallables)
570
- if (!declaredNames.has(name))
592
+ if (clientDeclared.has(name) && !declaredNames.has(name))
571
593
  findings.push({
572
594
  ...where,
573
- detail: `${name} is admin-only, but ${facts.adminDeclarations.modules.join(', ')} does not declare it`,
595
+ detail: `${name} is admin-only, but the client declares it outside ${facts.adminDeclarations.modules.join(', ')}`,
574
596
  });
575
597
  for (const root of facts.adminAreaRoots)
576
598
  if (!context.reader.exists(root))
@@ -590,9 +612,15 @@ export const adminActionSurfaceGuard = {
590
612
  continue;
591
613
  if (facts.adminAreaRoots.some((root) => isUnder(file.path, root)))
592
614
  continue;
615
+ const resolve = (spec) => resolveSpecifier(context.reader, file.path, spec, aliases);
593
616
  const uses = clientAdminUses(file, facts, (spec) => {
594
- const resolved = resolveSpecifier(context.reader, file.path, spec, aliases);
617
+ const resolved = resolve(spec);
595
618
  return declarationModules.has(resolved) ? resolved : null;
619
+ }, (spec) => {
620
+ const resolved = resolve(spec);
621
+ return facts.adminAreaRoots.some((root) => isUnder(resolved, root))
622
+ ? resolved
623
+ : null;
596
624
  });
597
625
  if (file.path === facts.affordanceOwner) {
598
626
  ownerHolds ||= uses.length > 0;
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/modules/backend/auth.ts"],"names":[],"mappings":"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","sourcesContent":["import ts from 'typescript';\nimport type { GenericGuardDefinition } from '../../node/suite/config.js';\nimport type { Finding, Guard, GuardContext } from '../../guard.js';\nimport type { Scope } from '../../node/reader.js';\nimport type { Reviewed } from '../../node/layout.js';\nimport type { FileView } from '../../reader/view.js';\nimport { ownerOnly, reviewedAllowlist, type Hit, type Matcher } from '../../shapes/shapes.js';\nimport { calleeName, forEachNode, lineOfNode } from '../../support/ast.js';\nimport {\n isText,\n namesProblem,\n objectProblem,\n pathProblem,\n reviewedProblems,\n takesNoFacts,\n textProblem,\n} from '../../support/facts.js';\nimport { MODULE_LOADS, moduleImports } from '../../support/imports.js';\nimport { aliasList, resolveSpecifier } from '../../support/resolve-specifier.js';\nimport { escapeRegExp, isUnder } from '../../support/text.js';\nimport {\n declarationFactProblems,\n readDeclarations,\n type CallableDeclarationFacts,\n} from '../frontend-actions/declarations.js';\nimport {\n inServerZone,\n serverZoneContext,\n serverZoneProblems,\n staleServerFolders,\n type ServerZone,\n} from './shared.js';\n\nconst FUNCTIONS_CODE: Scope = { roots: ['functions'], kinds: ['code'], tests: false };\n\nexport interface AdminClaimFacts {\n claimKeys: readonly string[];\n readers: readonly Reviewed[];\n appServerZone: ServerZone;\n}\n\nconst CLAIM_RECEIVER = String.raw`(?:[\\w$]*[Tt]oken|[\\w$]*[Cc]laims|decoded[\\w$]*)`;\n\nexport function adminClaimMatcher(claimKeys: readonly string[]): Matcher {\n const keys = claimKeys.map(escapeRegExp).join('|');\n const patterns = [\n new RegExp(String.raw`\\b${CLAIM_RECEIVER}\\s*(?:\\?\\.|\\.)\\s*(?:${keys})\\b`, 'g'),\n new RegExp(String.raw`\\b${CLAIM_RECEIVER}\\s*(?:\\?\\.)?\\s*\\[\\s*(['\"\\`])(?:${keys})\\1\\s*\\]`, 'g'),\n new RegExp(\n String.raw`\\{[^{}\\n]*\\b(?:${keys})\\b[^{}\\n]*\\}\\s*=\\s*[^;\\n]*${CLAIM_RECEIVER}\\b`,\n 'g',\n ),\n ];\n return (file) => {\n const hits: Hit[] = [];\n for (const re of patterns) {\n const g = new RegExp(re.source, re.flags);\n for (let m = g.exec(file.code); m; m = g.exec(file.code))\n hits.push({ index: m.index, detail: m[0].trim().slice(0, 80) });\n }\n return hits.sort((a, b) => a.index - b.index);\n };\n}\n\nexport const adminClaimGuard: GenericGuardDefinition<AdminClaimFacts> = {\n id: 'adminClaimRead',\n absentWhen: 'the app has no admin claim',\n factProblems(facts) {\n const problems: string[] = [];\n namesProblem(facts?.claimKeys, 'claimKeys', problems);\n reviewedProblems(facts?.readers, 'readers', problems, { nonEmpty: true });\n serverZoneProblems(facts?.appServerZone, 'appServerZone', problems);\n return problems;\n },\n build(facts) {\n const guard = reviewedAllowlist({\n title: 'the admin claim is read only by its resolver',\n description:\n `No server module reads an admin claim (${facts.claimKeys.join(', ')}) off a token or claims payload — by member ` +\n 'access, bracket access, or destructuring — outside the reviewed readers. The claim is metadata and stays true ' +\n 'for up to an hour after a demotion, and anything signed from it outlives the revocation by its own lifetime. ' +\n \"Resolve admin standing through the resolver's authoritative read, failing closed on a read failure. Writing the \" +\n 'claim is not a read. A reviewed reader that no longer reads the claim is stale.',\n scope: {\n roots: ['functions', 'app'],\n optionalRoots: ['functions'],\n kinds: ['code'],\n tests: false,\n },\n match: adminClaimMatcher(facts.claimKeys),\n allowlist: facts.readers,\n samples: {\n flags: [\n `if (request.auth.token.${facts.claimKeys[0]} === true) return all;`,\n `const a = decoded?.['${facts.claimKeys[0]}'];`,\n `const { uid, ${facts.claimKeys[0]} = false } = ctx.token;`,\n ],\n passes: [\n `await auth.setCustomUserClaims(uid, { ${facts.claimKeys[0]}: true });\\nif (args.${facts.claimKeys[0]}) run();`,\n ],\n },\n });\n return [\n {\n ...guard,\n async run(context: GuardContext) {\n return [\n ...staleServerFolders(context, facts.appServerZone),\n ...(await guard.run(serverZoneContext(context, facts.appServerZone))),\n ];\n },\n },\n ];\n },\n};\n\nexport interface RequestOriginFacts {\n reader: string;\n}\n\nconst ORIGIN_READ = /\\brawRequest\\b|x-forwarded-for|\\breq\\s*\\.\\s*ip\\b/gi;\n\nexport const requestOriginGuard: GenericGuardDefinition<RequestOriginFacts> = {\n id: 'requestOrigin',\n absentWhen: false,\n factProblems(facts) {\n const problems: string[] = [];\n textProblem(facts?.reader, 'reader', problems);\n return problems;\n },\n build(facts) {\n return [\n ownerOnly({\n title: \"a request's origin is read in one place\",\n description: `A request's origin is read only in ${facts.reader}, which must still hold the read.`,\n scope: FUNCTIONS_CODE,\n match: (file) => {\n const re = new RegExp(ORIGIN_READ.source, ORIGIN_READ.flags);\n const hits: Hit[] = [];\n for (let m = re.exec(file.code); m; m = re.exec(file.code))\n hits.push({ index: m.index, detail: m[0] });\n return hits;\n },\n owners: [facts.reader],\n samples: {\n flags: [\n 'const ip = request.rawRequest?.ip ?? null;',\n \"const hops = headers['x-forwarded-for'];\",\n 'const caller = req.ip;',\n 'const { rawRequest } = request;',\n ],\n passes: ['const facts = { ip: context.ip };\\n// rawRequest is read only by the reader'],\n },\n }),\n ];\n },\n};\n\nexport type NoBlockingFunctionFacts = Record<string, never>;\n\nconst BLOCKING_MODULE = /^firebase-functions\\/(?:v2\\/)?identity$/;\nconst BLOCKING_BUILDERS = new Set(['beforeCreate', 'beforeSignIn', 'beforeEmail', 'beforeSms']);\n\nexport function blockingFunctionSites(file: FileView): Array<{ node: ts.Node; detail: string }> {\n const out: Array<{ node: ts.Node; detail: string }> = [];\n for (const { spec, node } of moduleImports(file.sourceFile, MODULE_LOADS))\n if (BLOCKING_MODULE.test(spec)) out.push({ node, detail: `imports ${spec}` });\n forEachNode(file.sourceFile, (node) => {\n if (\n ts.isCallExpression(node) &&\n ts.isPropertyAccessExpression(node.expression) &&\n BLOCKING_BUILDERS.has(node.expression.name.text)\n ) {\n out.push({ node, detail: `registers ${node.expression.name.text}` });\n }\n });\n return out;\n}\n\nexport const noBlockingFunctionGuard: GenericGuardDefinition<NoBlockingFunctionFacts> = {\n id: 'noAuthBlockingFunction',\n absentWhen: false,\n factProblems: takesNoFacts,\n build() {\n return [\n {\n title: 'no sign-in waits on a blocking function',\n description:\n 'No Functions source registers an Identity Platform blocking function (the identity module, or a v1 ' +\n 'beforeCreate / beforeSignIn / beforeEmail / beforeSms builder). Identity Platform refuses a sign-up or ' +\n 'sign-in whose blocking function has not answered within seconds, and a cold instance can take longer than ' +\n 'that to start, so a blocking function refuses members at random. Do the work after the fact instead.',\n run(context) {\n return context.files(FUNCTIONS_CODE).flatMap((file) =>\n blockingFunctionSites(file).map(({ node, detail }) => ({\n file: file.path,\n line: lineOfNode(file, node),\n detail,\n })),\n );\n },\n },\n ];\n },\n};\n\nexport interface AppCheckFacts {\n consumingFolders: readonly string[];\n adminAuth: { call: string; option: string };\n consumptionExempt: ReadonlyArray<{ callable: string; why: string }>;\n clientDeclarations: CallableDeclarationFacts;\n noClientDeclaration: ReadonlyArray<{ callable: string; why: string }>;\n}\n\ninterface Callable {\n name: string;\n node: ts.Node;\n options: ts.ObjectLiteralExpression | null;\n}\n\nconst isOnCall = (node: ts.Node): node is ts.CallExpression =>\n ts.isCallExpression(node) &&\n ts.isIdentifier(node.expression) &&\n node.expression.text === 'onCall';\n\nconst declaresTrue = (options: ts.ObjectLiteralExpression | null, key: string) =>\n !!options?.properties.some(\n (p) =>\n ts.isPropertyAssignment(p) &&\n p.name.getText().replace(/^['\"]|['\"]$/g, '') === key &&\n p.initializer.kind === ts.SyntaxKind.TrueKeyword,\n );\n\nexport function callablesOf(file: FileView): Callable[] {\n const sf = file.sourceFile;\n const optionsOf = (call: ts.CallExpression) =>\n call.arguments[0] && ts.isObjectLiteralExpression(call.arguments[0]) ? call.arguments[0] : null;\n const factories = new Map<string, ts.CallExpression>();\n const named = new Set<ts.CallExpression>();\n const out: Callable[] = [];\n forEachNode(sf, (node) => {\n if (ts.isFunctionDeclaration(node) && node.name && node.body) {\n forEachNode(node.body, (n) => {\n if (ts.isReturnStatement(n) && n.expression && isOnCall(n.expression))\n factories.set(node.name!.text, n.expression);\n });\n }\n });\n forEachNode(sf, (node) => {\n if (\n !ts.isVariableDeclaration(node) ||\n !ts.isIdentifier(node.name) ||\n !node.initializer ||\n !ts.isCallExpression(node.initializer)\n )\n return;\n const init: ts.CallExpression = node.initializer;\n if (isOnCall(init as ts.Node)) {\n named.add(init);\n out.push({ name: node.name.text, node: init, options: optionsOf(init) });\n } else if (ts.isIdentifier(init.expression) && factories.has(init.expression.text)) {\n const made = factories.get(init.expression.text)!;\n named.add(made);\n out.push({ name: node.name.text, node: init, options: optionsOf(made) });\n }\n });\n forEachNode(sf, (node) => {\n if (isOnCall(node) && !named.has(node))\n out.push({\n name: `(onCall at line ${lineOfNode(file, node)})`,\n node,\n options: optionsOf(node),\n });\n });\n return out;\n}\n\nexport function asksForAdmin(file: FileView, adminAuth: AppCheckFacts['adminAuth']): boolean {\n let found = false;\n forEachNode(file.sourceFile, (node) => {\n if (found || !ts.isCallExpression(node) || calleeName(node) !== adminAuth.call) return;\n found = node.arguments.some(\n (arg) =>\n ts.isObjectLiteralExpression(arg) &&\n arg.properties.some(\n (p) => p.name?.getText().replace(/^['\"]|['\"]$/g, '') === adminAuth.option,\n ),\n );\n });\n return found;\n}\n\nexport const appCheckGuard: GenericGuardDefinition<AppCheckFacts> = {\n id: 'appCheck',\n absentWhen: 'the app has no callable functions',\n factProblems(facts) {\n const problems: string[] = [];\n namesProblem(facts?.consumingFolders, 'consumingFolders', problems, { nonEmpty: false });\n textProblem(facts?.adminAuth?.call, 'adminAuth.call', problems);\n textProblem(facts?.adminAuth?.option, 'adminAuth.option', problems);\n reviewedProblems(facts?.consumptionExempt, 'consumptionExempt', problems, { key: 'callable' });\n declarationFactProblems(facts?.clientDeclarations, 'clientDeclarations', problems);\n reviewedProblems(facts?.noClientDeclaration, 'noClientDeclaration', problems, {\n key: 'callable',\n });\n return problems;\n },\n build(facts) {\n const posture: Guard = {\n title: 'every callable declares its App Check posture',\n description:\n 'Every `onCall` opens with a literal options object (one this check cannot read fails, never passes) that ' +\n 'declares `enforceAppCheck: true`: attestation sits beneath auth and neither substitutes for the other. A ' +\n `callable in a consuming folder (${facts.consumingFolders.join(', ') || 'none declared'}), and every callable in a ` +\n `file whose ${facts.adminAuth.call} asks for ${facts.adminAuth.option}, also declares \\`consumeAppCheckToken: true\\`, ` +\n 'so its attestation token is spent instead of reusable for its whole lifetime. A callable that keeps the cached ' +\n 'token is a reviewed exemption with its why; an exemption whose callable is gone or now consumes is stale.',\n run(context) {\n const findings: Finding[] = [];\n const exempt = new Map(facts.consumptionExempt.map((e) => [e.callable, e]));\n const exemptSeen = new Set<string>();\n const foldersWithCallables = new Set<string>();\n let callables = 0;\n for (const file of context.files(FUNCTIONS_CODE)) {\n const list = callablesOf(file);\n if (!list.length) continue;\n callables += list.length;\n const folder = facts.consumingFolders.find((f) => isUnder(file.path, f));\n if (folder) foldersWithCallables.add(folder);\n const mustConsume = !!folder || asksForAdmin(file, facts.adminAuth);\n for (const callable of list) {\n const line = lineOfNode(file, callable.node);\n if (!callable.options) {\n findings.push({\n file: file.path,\n line,\n detail: `${callable.name}: the onCall options are not an object literal, so the posture cannot be read`,\n });\n continue;\n }\n if (!declaresTrue(callable.options, 'enforceAppCheck'))\n findings.push({\n file: file.path,\n line,\n detail: `${callable.name}: no enforceAppCheck: true`,\n });\n const consumes = declaresTrue(callable.options, 'consumeAppCheckToken');\n if (exempt.has(callable.name)) {\n exemptSeen.add(callable.name);\n if (consumes)\n findings.push({\n file: file.path,\n line,\n detail: `stale exemption: ${callable.name} now consumes its token`,\n });\n else if (!mustConsume)\n findings.push({\n file: file.path,\n line,\n detail: `stale exemption: ${callable.name} is not a consuming callable`,\n });\n } else if (mustConsume && !consumes) {\n findings.push({\n file: file.path,\n line,\n detail: `${callable.name}: no consumeAppCheckToken: true`,\n });\n }\n }\n }\n if (!callables)\n findings.push({\n file: '(functions)',\n detail: 'no onCall found, so the guard checks nothing',\n });\n for (const folder of facts.consumingFolders)\n if (!foldersWithCallables.has(folder))\n findings.push({ file: folder, detail: 'stale consuming folder: it holds no callable' });\n for (const name of exempt.keys())\n if (!exemptSeen.has(name))\n findings.push({\n file: '(consumptionExempt)',\n detail: `stale exemption: no callable is named ${name}`,\n });\n return findings;\n },\n };\n const client: Guard = {\n title: \"a consuming callable's client declaration presents a limited-use token\",\n description:\n 'Every callable whose options declare `consumeAppCheckToken: true` has a client declaration in ' +\n `${facts.clientDeclarations.modules.join(', ')} carrying \\`limitedUseAppCheck: true\\`, so the token the server ` +\n 'spends is a single-use one rather than the cached token every other call reuses. A declaration carrying it names ' +\n 'a callable that consumes: one that names no callable, or a callable that keeps the cached token (an exempt one ' +\n 'included), mints a token per call for nothing. A consuming callable no client calls is a reviewed entry with ' +\n 'its why; an entry that is no longer a consuming callable, or that a declaration now names, is stale.',\n run(context) {\n const { declared, findings } = readDeclarations(context, facts.clientDeclarations);\n const servers = new Map<string, { consumes: boolean; file: string; line: number }>();\n for (const file of context.files(FUNCTIONS_CODE)) {\n for (const callable of callablesOf(file)) {\n servers.set(callable.name, {\n consumes: declaresTrue(callable.options, 'consumeAppCheckToken'),\n file: file.path,\n line: lineOfNode(file, callable.node),\n });\n }\n }\n if (!servers.size)\n findings.push({\n file: '(functions)',\n detail: 'no onCall found, so the guard checks nothing',\n });\n const byName = new Map(\n declared.filter((d) => d.callable !== null).map((d) => [d.callable!, d]),\n );\n const exempt = new Set(facts.consumptionExempt.map((e) => e.callable));\n const undeclared = new Set(facts.noClientDeclaration.map((e) => e.callable));\n for (const [name, server] of servers) {\n if (!server.consumes) continue;\n const declaration = byName.get(name);\n if (!declaration) {\n if (!undeclared.has(name))\n findings.push({\n file: server.file,\n line: server.line,\n detail: `${name} consumes its token, but no client declaration names it`,\n });\n } else if (!declaration.limitedUse) {\n findings.push({\n file: declaration.file,\n line: declaration.line,\n detail: `${declaration.hook} declares ${name}, which consumes its token, without limitedUseAppCheck: true`,\n });\n }\n }\n for (const declaration of declared) {\n if (!declaration.limitedUse || declaration.callable === null) continue;\n const server = servers.get(declaration.callable);\n const where = { file: declaration.file, line: declaration.line };\n if (!server)\n findings.push({\n ...where,\n detail: `${declaration.hook} declares ${declaration.callable} limited-use, but no callable of that name exists`,\n });\n else if (exempt.has(declaration.callable))\n findings.push({\n ...where,\n detail: `${declaration.hook} declares ${declaration.callable} limited-use, but it is exempt from consumption`,\n });\n else if (!server.consumes)\n findings.push({\n ...where,\n detail: `${declaration.hook} declares ${declaration.callable} limited-use, but it does not consume its token`,\n });\n }\n for (const name of undeclared) {\n if (byName.has(name))\n findings.push({\n file: '(noClientDeclaration)',\n detail: `stale entry: a client declaration names ${name} now`,\n });\n else if (!servers.get(name)?.consumes)\n findings.push({\n file: '(noClientDeclaration)',\n detail: `stale entry: ${name} is not a consuming callable`,\n });\n }\n return findings;\n },\n };\n return [posture, client];\n },\n};\n\nexport interface AdminActionSurfaceFacts {\n adminAuth: { call: string; option: string };\n adminCheckers: readonly string[];\n checkerReaders: readonly Reviewed[];\n adminDeclarations: CallableDeclarationFacts;\n claimKeys: readonly string[];\n adminHooks: readonly string[];\n adminAreaRoots: readonly string[];\n affordanceOwner: string;\n reviewed: ReadonlyArray<{ path: string; symbol?: string; why: string }>;\n importAliases: Readonly<Record<string, string>>;\n appServerZone: ServerZone;\n}\n\nconst APP_CLIENT_CODE: Scope = { roots: ['app'], kinds: ['code'], tests: false };\n\nfunction authCallsIn(root: ts.Node, adminAuth: AdminActionSurfaceFacts['adminAuth']) {\n const calls: Array<{ admin: boolean }> = [];\n forEachNode(root, (node) => {\n if (!ts.isCallExpression(node) || calleeName(node) !== adminAuth.call) return;\n calls.push({\n admin: node.arguments.some(\n (arg) =>\n ts.isObjectLiteralExpression(arg) &&\n arg.properties.some(\n (p) =>\n p.name?.getText().replace(/^['\"]|['\"]$/g, '') === adminAuth.option &&\n !(ts.isPropertyAssignment(p) && isOffLiteral(p.initializer)),\n ),\n ),\n });\n });\n return calls;\n}\n\nconst isOffLiteral = (value: ts.Expression): boolean =>\n value.kind === ts.SyntaxKind.FalseKeyword ||\n value.kind === ts.SyntaxKind.NullKeyword ||\n (ts.isIdentifier(value) && value.text === 'undefined');\n\nexport function adminOnlyCallables(\n file: FileView,\n adminAuth: AdminActionSurfaceFacts['adminAuth'],\n): string[] {\n const moduleCalls = authCallsIn(file.sourceFile, adminAuth);\n return callablesOf(file)\n .filter((callable) => {\n const own = authCallsIn(callable.node, adminAuth);\n const calls = own.length ? own : moduleCalls;\n return calls.length > 0 && calls.every((c) => c.admin);\n })\n .map((callable) => callable.name);\n}\n\ninterface ClientAdminUse {\n index: number;\n symbol: string;\n detail: string;\n}\n\nexport function clientAdminUses(\n file: FileView,\n facts: Pick<AdminActionSurfaceFacts, 'claimKeys' | 'adminHooks'>,\n declarationModuleOf: (spec: string) => string | null,\n): ClientAdminUse[] {\n const out: ClientAdminUse[] = [];\n const keys = new RegExp(`\\\\b(${facts.claimKeys.map(escapeRegExp).join('|')})\\\\b`);\n for (const hit of adminClaimMatcher(facts.claimKeys)(file))\n out.push({\n index: hit.index,\n symbol: keys.exec(hit.detail ?? '')?.[1] ?? '',\n detail: `reads the admin claim (${hit.detail})`,\n });\n const hooks = new Set(facts.adminHooks);\n for (const site of moduleImports(file.sourceFile, MODULE_LOADS)) {\n const index = site.node.getStart(file.sourceFile);\n const module = declarationModuleOf(site.spec);\n if (module) {\n const names = site.named.map((n) => n.imported);\n for (const symbol of names.length ? names : ['*'])\n out.push({\n index,\n symbol,\n detail: `imports ${symbol} from the admin declarations ${module}`,\n });\n continue;\n }\n for (const name of site.named)\n if (hooks.has(name.imported))\n out.push({\n index,\n symbol: name.imported,\n detail: `imports the admin hook ${name.imported}`,\n });\n }\n return out.sort((a, b) => a.index - b.index);\n}\n\nfunction adminAreaProblems(facts: AdminActionSurfaceFacts | undefined, problems: string[]): void {\n if (!Array.isArray(facts?.adminAreaRoots) || !facts.adminAreaRoots.length)\n problems.push('adminAreaRoots is missing');\n else facts.adminAreaRoots.forEach((r, i) => pathProblem(r, `adminAreaRoots[${i}]`, problems));\n pathProblem(facts?.affordanceOwner, 'affordanceOwner', problems);\n reviewedProblems(facts?.reviewed, 'reviewed', problems, {\n id: (e) =>\n typeof e.path === 'string' ? `${e.path}${isText(e.symbol) ? ` ${e.symbol}` : ''}` : undefined,\n extra(entry, label) {\n if (entry.symbol !== undefined && !isText(entry.symbol))\n problems.push(`${label}'s symbol is empty`);\n },\n });\n}\n\nexport const adminActionSurfaceGuard: GenericGuardDefinition<AdminActionSurfaceFacts> = {\n id: 'adminActionSurface',\n absentWhen: 'the app has no admin actions',\n factProblems(facts) {\n const problems: string[] = [];\n if (objectProblem(facts?.adminAuth, 'adminAuth', problems)) {\n textProblem(facts.adminAuth.call, 'adminAuth.call', problems);\n textProblem(facts.adminAuth.option, 'adminAuth.option', problems);\n }\n namesProblem(facts?.adminCheckers, 'adminCheckers', problems);\n reviewedProblems(facts?.checkerReaders, 'checkerReaders', problems);\n declarationFactProblems(facts?.adminDeclarations, 'adminDeclarations', problems);\n namesProblem(facts?.claimKeys, 'claimKeys', problems);\n namesProblem(facts?.adminHooks, 'adminHooks', problems, { nonEmpty: false });\n adminAreaProblems(facts, problems);\n objectProblem(facts?.importAliases, 'importAliases', problems);\n serverZoneProblems(facts?.appServerZone, 'appServerZone', problems);\n return problems;\n },\n build(facts) {\n const declarationModules = new Set(facts.adminDeclarations.modules);\n const probePath = `${facts.affordanceOwner.slice(0, facts.affordanceOwner.lastIndexOf('/') + 1)}probe.tsx`;\n return [\n {\n title: 'admin actions outside the admin area go through the admin-actions affordance',\n description:\n `The admin-only callables are every callable whose ${facts.adminAuth.call} calls all carry ` +\n `${facts.adminAuth.option}, read from the Functions source each run. Inside a callable module, admin standing ` +\n `is checked only through that auth call: ${facts.adminCheckers.join(', ')} is called only by the reviewed ` +\n `readers. ${facts.adminDeclarations.modules.join(', ')} declares exactly the admin-only callables, no more and ` +\n `no fewer. Outside the admin area (${facts.adminAreaRoots.join(', ')}) and the admin-actions affordance ` +\n `(${facts.affordanceOwner}), client code never reads the admin claim, imports an admin declaration, or imports ` +\n 'an admin hook: an admin action there goes through the affordance, and any other admin-standing read is a ' +\n 'reviewed entry ({ path, symbol?, why }). A reviewed reader or entry that no longer matches is stale.',\n samples: {\n flags: [\n { path: probePath, text: `if (claims?.${facts.claimKeys[0]}) show();` },\n ...facts.adminHooks\n .slice(0, 1)\n .map((hook) => ({ path: probePath, text: `import { ${hook} } from './hooks';` })),\n ],\n passes: [\n { path: probePath, text: `const label = '${facts.claimKeys[0]}';` },\n { path: probePath, text: \"import { useRows } from './hooks';\" },\n ],\n probe: (view) => clientAdminUses(view, facts, () => null),\n },\n run(context) {\n const findings: Finding[] = [];\n const adminCallables = new Map<string, { file: string; line: number }>();\n const readers = new Map(facts.checkerReaders.map((r) => [r.path, false]));\n const checkers = new Set(facts.adminCheckers);\n for (const file of context.files(FUNCTIONS_CODE)) {\n const callables = callablesOf(file);\n if (!callables.length) continue;\n for (const name of adminOnlyCallables(file, facts.adminAuth)) {\n const callable = callables.find((c) => c.name === name)!;\n adminCallables.set(name, { file: file.path, line: lineOfNode(file, callable.node) });\n }\n forEachNode(file.sourceFile, (node) => {\n if (!ts.isCallExpression(node)) return;\n const name = calleeName(node);\n if (!name || !checkers.has(name)) return;\n if (readers.has(file.path)) readers.set(file.path, true);\n else\n findings.push({\n file: file.path,\n line: lineOfNode(file, node),\n detail: `a callable module checks admin standing through ${name} instead of its ${facts.adminAuth.call}`,\n });\n });\n }\n for (const [path, used] of readers)\n if (!used)\n findings.push({\n file: path,\n detail: 'stale reader: it no longer calls an admin checker in a callable module',\n });\n if (!adminCallables.size)\n findings.push({\n file: '(functions)',\n detail: `no callable asks ${facts.adminAuth.call} for ${facts.adminAuth.option}, so no admin-only callable was found`,\n });\n\n const { declared, findings: declarationFindings } = readDeclarations(\n context,\n facts.adminDeclarations,\n );\n findings.push(...declarationFindings);\n const declaredNames = new Set<string>();\n for (const d of declared) {\n if (d.callable === null) continue;\n declaredNames.add(d.callable);\n if (!adminCallables.has(d.callable))\n findings.push({\n file: d.file,\n line: d.line,\n detail: `${d.hook} declares ${d.callable}, which is not an admin-only callable`,\n });\n }\n for (const [name, where] of adminCallables)\n if (!declaredNames.has(name))\n findings.push({\n ...where,\n detail: `${name} is admin-only, but ${facts.adminDeclarations.modules.join(', ')} does not declare it`,\n });\n\n for (const root of facts.adminAreaRoots)\n if (!context.reader.exists(root))\n findings.push({ file: root, detail: 'stale admin-area root: it no longer exists' });\n const ownerExists = context.reader.exists(facts.affordanceOwner);\n if (!ownerExists)\n findings.push({\n file: facts.affordanceOwner,\n detail: 'the admin-actions affordance no longer exists',\n });\n const aliases = aliasList(facts.importAliases);\n const reviewedKey = (e: { path: string; symbol?: string }) =>\n `${e.path}${e.symbol ? ` ${e.symbol}` : ''}`;\n const reviewedSeen = new Set<string>();\n let ownerHolds = false;\n for (const file of context.files(APP_CLIENT_CODE)) {\n if (inServerZone(file, facts.appServerZone)) continue;\n if (facts.adminAreaRoots.some((root) => isUnder(file.path, root))) continue;\n const uses = clientAdminUses(file, facts, (spec) => {\n const resolved = resolveSpecifier(context.reader, file.path, spec, aliases);\n return declarationModules.has(resolved) ? resolved : null;\n });\n if (file.path === facts.affordanceOwner) {\n ownerHolds ||= uses.length > 0;\n continue;\n }\n for (const use of uses) {\n const entry = facts.reviewed.find(\n (e) => e.path === file.path && (e.symbol === undefined || e.symbol === use.symbol),\n );\n if (entry) reviewedSeen.add(reviewedKey(entry));\n else\n findings.push({\n file: file.path,\n line: file.lineOf(use.index),\n detail: `outside the admin area: ${use.detail}`,\n });\n }\n }\n if (ownerExists && !ownerHolds)\n findings.push({\n file: facts.affordanceOwner,\n detail:\n 'stale affordance owner: it reads no admin standing and imports no admin declaration or hook',\n });\n for (const entry of facts.reviewed)\n if (!reviewedSeen.has(reviewedKey(entry)))\n findings.push({\n file: entry.path,\n detail: `stale entry: it no longer reads admin standing${entry.symbol ? ` through ${entry.symbol}` : ''}`,\n });\n return findings;\n },\n },\n ];\n },\n};\n"]}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/modules/backend/auth.ts"],"names":[],"mappings":"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","sourcesContent":["import ts from 'typescript';\nimport type { GenericGuardDefinition } from '../../node/suite/config.js';\nimport type { Finding, Guard, GuardContext } from '../../guard.js';\nimport type { Scope } from '../../node/reader.js';\nimport type { Reviewed } from '../../node/layout.js';\nimport type { FileView } from '../../reader/view.js';\nimport { ownerOnly, reviewedAllowlist, type Hit, type Matcher } from '../../shapes/shapes.js';\nimport { calleeName, forEachNode, lineOfNode } from '../../support/ast.js';\nimport {\n isText,\n namesProblem,\n objectProblem,\n pathProblem,\n reviewedProblems,\n takesNoFacts,\n textProblem,\n} from '../../support/facts.js';\nimport { MODULE_LOADS, moduleImports } from '../../support/imports.js';\nimport { aliasList, resolveSpecifier } from '../../support/resolve-specifier.js';\nimport { escapeRegExp, isUnder } from '../../support/text.js';\nimport {\n declarationFactProblems,\n readDeclarations,\n type CallableDeclarationFacts,\n} from '../frontend-actions/declarations.js';\nimport {\n inServerZone,\n serverZoneContext,\n serverZoneProblems,\n staleServerFolders,\n type ServerZone,\n} from './shared.js';\n\nconst FUNCTIONS_CODE: Scope = { roots: ['functions'], kinds: ['code'], tests: false };\n\nexport interface AdminClaimFacts {\n claimKeys: readonly string[];\n readers: readonly Reviewed[];\n appServerZone: ServerZone;\n}\n\nconst CLAIM_RECEIVER = String.raw`(?:[\\w$]*[Tt]oken|[\\w$]*[Cc]laims|decoded[\\w$]*)`;\n\nexport function adminClaimMatcher(claimKeys: readonly string[]): Matcher {\n const keys = claimKeys.map(escapeRegExp).join('|');\n const patterns = [\n new RegExp(String.raw`\\b${CLAIM_RECEIVER}\\s*(?:\\?\\.|\\.)\\s*(?:${keys})\\b`, 'g'),\n new RegExp(String.raw`\\b${CLAIM_RECEIVER}\\s*(?:\\?\\.)?\\s*\\[\\s*(['\"\\`])(?:${keys})\\1\\s*\\]`, 'g'),\n new RegExp(\n String.raw`\\{[^{}\\n]*\\b(?:${keys})\\b[^{}\\n]*\\}\\s*=\\s*[^;\\n]*${CLAIM_RECEIVER}\\b`,\n 'g',\n ),\n ];\n return (file) => {\n const hits: Hit[] = [];\n for (const re of patterns) {\n const g = new RegExp(re.source, re.flags);\n for (let m = g.exec(file.code); m; m = g.exec(file.code))\n hits.push({ index: m.index, detail: m[0].trim().slice(0, 80) });\n }\n return hits.sort((a, b) => a.index - b.index);\n };\n}\n\nexport const adminClaimGuard: GenericGuardDefinition<AdminClaimFacts> = {\n id: 'adminClaimRead',\n absentWhen: 'the app has no admin claim',\n factProblems(facts) {\n const problems: string[] = [];\n namesProblem(facts?.claimKeys, 'claimKeys', problems);\n reviewedProblems(facts?.readers, 'readers', problems, { nonEmpty: true });\n serverZoneProblems(facts?.appServerZone, 'appServerZone', problems);\n return problems;\n },\n build(facts) {\n const guard = reviewedAllowlist({\n title: 'the admin claim is read only by its resolver',\n description:\n `No server module reads an admin claim (${facts.claimKeys.join(', ')}) off a token or claims payload — by member ` +\n 'access, bracket access, or destructuring — outside the reviewed readers. The claim is metadata and stays true ' +\n 'for up to an hour after a demotion, and anything signed from it outlives the revocation by its own lifetime. ' +\n \"Resolve admin standing through the resolver's authoritative read, failing closed on a read failure. Writing the \" +\n 'claim is not a read. A reviewed reader that no longer reads the claim is stale.',\n scope: {\n roots: ['functions', 'app'],\n optionalRoots: ['functions'],\n kinds: ['code'],\n tests: false,\n },\n match: adminClaimMatcher(facts.claimKeys),\n allowlist: facts.readers,\n samples: {\n flags: [\n `if (request.auth.token.${facts.claimKeys[0]} === true) return all;`,\n `const a = decoded?.['${facts.claimKeys[0]}'];`,\n `const { uid, ${facts.claimKeys[0]} = false } = ctx.token;`,\n ],\n passes: [\n `await auth.setCustomUserClaims(uid, { ${facts.claimKeys[0]}: true });\\nif (args.${facts.claimKeys[0]}) run();`,\n ],\n },\n });\n return [\n {\n ...guard,\n async run(context: GuardContext) {\n return [\n ...staleServerFolders(context, facts.appServerZone),\n ...(await guard.run(serverZoneContext(context, facts.appServerZone))),\n ];\n },\n },\n ];\n },\n};\n\nexport interface RequestOriginFacts {\n reader: string;\n}\n\nconst ORIGIN_READ = /\\brawRequest\\b|x-forwarded-for|\\breq\\s*\\.\\s*ip\\b/gi;\n\nexport const requestOriginGuard: GenericGuardDefinition<RequestOriginFacts> = {\n id: 'requestOrigin',\n absentWhen: false,\n factProblems(facts) {\n const problems: string[] = [];\n textProblem(facts?.reader, 'reader', problems);\n return problems;\n },\n build(facts) {\n return [\n ownerOnly({\n title: \"a request's origin is read in one place\",\n description: `A request's origin is read only in ${facts.reader}, which must still hold the read.`,\n scope: FUNCTIONS_CODE,\n match: (file) => {\n const re = new RegExp(ORIGIN_READ.source, ORIGIN_READ.flags);\n const hits: Hit[] = [];\n for (let m = re.exec(file.code); m; m = re.exec(file.code))\n hits.push({ index: m.index, detail: m[0] });\n return hits;\n },\n owners: [facts.reader],\n samples: {\n flags: [\n 'const ip = request.rawRequest?.ip ?? null;',\n \"const hops = headers['x-forwarded-for'];\",\n 'const caller = req.ip;',\n 'const { rawRequest } = request;',\n ],\n passes: ['const facts = { ip: context.ip };\\n// rawRequest is read only by the reader'],\n },\n }),\n ];\n },\n};\n\nexport type NoBlockingFunctionFacts = Record<string, never>;\n\nconst BLOCKING_MODULE = /^firebase-functions\\/(?:v2\\/)?identity$/;\nconst BLOCKING_BUILDERS = new Set(['beforeCreate', 'beforeSignIn', 'beforeEmail', 'beforeSms']);\n\nexport function blockingFunctionSites(file: FileView): Array<{ node: ts.Node; detail: string }> {\n const out: Array<{ node: ts.Node; detail: string }> = [];\n for (const { spec, node } of moduleImports(file.sourceFile, MODULE_LOADS))\n if (BLOCKING_MODULE.test(spec)) out.push({ node, detail: `imports ${spec}` });\n forEachNode(file.sourceFile, (node) => {\n if (\n ts.isCallExpression(node) &&\n ts.isPropertyAccessExpression(node.expression) &&\n BLOCKING_BUILDERS.has(node.expression.name.text)\n ) {\n out.push({ node, detail: `registers ${node.expression.name.text}` });\n }\n });\n return out;\n}\n\nexport const noBlockingFunctionGuard: GenericGuardDefinition<NoBlockingFunctionFacts> = {\n id: 'noAuthBlockingFunction',\n absentWhen: false,\n factProblems: takesNoFacts,\n build() {\n return [\n {\n title: 'no sign-in waits on a blocking function',\n description:\n 'No Functions source registers an Identity Platform blocking function (the identity module, or a v1 ' +\n 'beforeCreate / beforeSignIn / beforeEmail / beforeSms builder). Identity Platform refuses a sign-up or ' +\n 'sign-in whose blocking function has not answered within seconds, and a cold instance can take longer than ' +\n 'that to start, so a blocking function refuses members at random. Do the work after the fact instead.',\n run(context) {\n return context.files(FUNCTIONS_CODE).flatMap((file) =>\n blockingFunctionSites(file).map(({ node, detail }) => ({\n file: file.path,\n line: lineOfNode(file, node),\n detail,\n })),\n );\n },\n },\n ];\n },\n};\n\nexport interface AppCheckFacts {\n consumingFolders: readonly string[];\n adminAuth: { call: string; option: string };\n consumptionExempt: ReadonlyArray<{ callable: string; why: string }>;\n clientDeclarations: CallableDeclarationFacts;\n noClientDeclaration: ReadonlyArray<{ callable: string; why: string }>;\n}\n\ninterface Callable {\n name: string;\n node: ts.Node;\n options: ts.ObjectLiteralExpression | null;\n}\n\nconst isOnCall = (node: ts.Node): node is ts.CallExpression =>\n ts.isCallExpression(node) &&\n ts.isIdentifier(node.expression) &&\n node.expression.text === 'onCall';\n\nconst declaresTrue = (options: ts.ObjectLiteralExpression | null, key: string) =>\n !!options?.properties.some(\n (p) =>\n ts.isPropertyAssignment(p) &&\n p.name.getText().replace(/^['\"]|['\"]$/g, '') === key &&\n p.initializer.kind === ts.SyntaxKind.TrueKeyword,\n );\n\nexport function callablesOf(file: FileView): Callable[] {\n const sf = file.sourceFile;\n const optionsOf = (call: ts.CallExpression) =>\n call.arguments[0] && ts.isObjectLiteralExpression(call.arguments[0]) ? call.arguments[0] : null;\n const factories = new Map<string, ts.CallExpression>();\n const named = new Set<ts.CallExpression>();\n const out: Callable[] = [];\n forEachNode(sf, (node) => {\n if (ts.isFunctionDeclaration(node) && node.name && node.body) {\n forEachNode(node.body, (n) => {\n if (ts.isReturnStatement(n) && n.expression && isOnCall(n.expression))\n factories.set(node.name!.text, n.expression);\n });\n }\n });\n forEachNode(sf, (node) => {\n if (\n !ts.isVariableDeclaration(node) ||\n !ts.isIdentifier(node.name) ||\n !node.initializer ||\n !ts.isCallExpression(node.initializer)\n )\n return;\n const init: ts.CallExpression = node.initializer;\n if (isOnCall(init as ts.Node)) {\n named.add(init);\n out.push({ name: node.name.text, node: init, options: optionsOf(init) });\n } else if (ts.isIdentifier(init.expression) && factories.has(init.expression.text)) {\n const made = factories.get(init.expression.text)!;\n named.add(made);\n out.push({ name: node.name.text, node: init, options: optionsOf(made) });\n }\n });\n forEachNode(sf, (node) => {\n if (isOnCall(node) && !named.has(node))\n out.push({\n name: `(onCall at line ${lineOfNode(file, node)})`,\n node,\n options: optionsOf(node),\n });\n });\n return out;\n}\n\nexport function asksForAdmin(file: FileView, adminAuth: AppCheckFacts['adminAuth']): boolean {\n let found = false;\n forEachNode(file.sourceFile, (node) => {\n if (found || !ts.isCallExpression(node) || calleeName(node) !== adminAuth.call) return;\n found = node.arguments.some(\n (arg) =>\n ts.isObjectLiteralExpression(arg) &&\n arg.properties.some(\n (p) => p.name?.getText().replace(/^['\"]|['\"]$/g, '') === adminAuth.option,\n ),\n );\n });\n return found;\n}\n\nexport const appCheckGuard: GenericGuardDefinition<AppCheckFacts> = {\n id: 'appCheck',\n absentWhen: 'the app has no callable functions',\n factProblems(facts) {\n const problems: string[] = [];\n namesProblem(facts?.consumingFolders, 'consumingFolders', problems, { nonEmpty: false });\n textProblem(facts?.adminAuth?.call, 'adminAuth.call', problems);\n textProblem(facts?.adminAuth?.option, 'adminAuth.option', problems);\n reviewedProblems(facts?.consumptionExempt, 'consumptionExempt', problems, { key: 'callable' });\n declarationFactProblems(facts?.clientDeclarations, 'clientDeclarations', problems);\n reviewedProblems(facts?.noClientDeclaration, 'noClientDeclaration', problems, {\n key: 'callable',\n });\n return problems;\n },\n build(facts) {\n const posture: Guard = {\n title: 'every callable declares its App Check posture',\n description:\n 'Every `onCall` opens with a literal options object (one this check cannot read fails, never passes) that ' +\n 'declares `enforceAppCheck: true`: attestation sits beneath auth and neither substitutes for the other. A ' +\n `callable in a consuming folder (${facts.consumingFolders.join(', ') || 'none declared'}), and every callable in a ` +\n `file whose ${facts.adminAuth.call} asks for ${facts.adminAuth.option}, also declares \\`consumeAppCheckToken: true\\`, ` +\n 'so its attestation token is spent instead of reusable for its whole lifetime. A callable that keeps the cached ' +\n 'token is a reviewed exemption with its why; an exemption whose callable is gone or now consumes is stale.',\n run(context) {\n const findings: Finding[] = [];\n const exempt = new Map(facts.consumptionExempt.map((e) => [e.callable, e]));\n const exemptSeen = new Set<string>();\n const foldersWithCallables = new Set<string>();\n let callables = 0;\n for (const file of context.files(FUNCTIONS_CODE)) {\n const list = callablesOf(file);\n if (!list.length) continue;\n callables += list.length;\n const folder = facts.consumingFolders.find((f) => isUnder(file.path, f));\n if (folder) foldersWithCallables.add(folder);\n const mustConsume = !!folder || asksForAdmin(file, facts.adminAuth);\n for (const callable of list) {\n const line = lineOfNode(file, callable.node);\n if (!callable.options) {\n findings.push({\n file: file.path,\n line,\n detail: `${callable.name}: the onCall options are not an object literal, so the posture cannot be read`,\n });\n continue;\n }\n if (!declaresTrue(callable.options, 'enforceAppCheck'))\n findings.push({\n file: file.path,\n line,\n detail: `${callable.name}: no enforceAppCheck: true`,\n });\n const consumes = declaresTrue(callable.options, 'consumeAppCheckToken');\n if (exempt.has(callable.name)) {\n exemptSeen.add(callable.name);\n if (consumes)\n findings.push({\n file: file.path,\n line,\n detail: `stale exemption: ${callable.name} now consumes its token`,\n });\n else if (!mustConsume)\n findings.push({\n file: file.path,\n line,\n detail: `stale exemption: ${callable.name} is not a consuming callable`,\n });\n } else if (mustConsume && !consumes) {\n findings.push({\n file: file.path,\n line,\n detail: `${callable.name}: no consumeAppCheckToken: true`,\n });\n }\n }\n }\n if (!callables)\n findings.push({\n file: '(functions)',\n detail: 'no onCall found, so the guard checks nothing',\n });\n for (const folder of facts.consumingFolders)\n if (!foldersWithCallables.has(folder))\n findings.push({ file: folder, detail: 'stale consuming folder: it holds no callable' });\n for (const name of exempt.keys())\n if (!exemptSeen.has(name))\n findings.push({\n file: '(consumptionExempt)',\n detail: `stale exemption: no callable is named ${name}`,\n });\n return findings;\n },\n };\n const client: Guard = {\n title: \"a consuming callable's client declaration presents a limited-use token\",\n description:\n 'Every callable whose options declare `consumeAppCheckToken: true` has a client declaration in ' +\n `${facts.clientDeclarations.modules.join(', ')} carrying \\`limitedUseAppCheck: true\\`, so the token the server ` +\n 'spends is a single-use one rather than the cached token every other call reuses. A declaration carrying it names ' +\n 'a callable that consumes: one that names no callable, or a callable that keeps the cached token (an exempt one ' +\n 'included), mints a token per call for nothing. A consuming callable no client calls is a reviewed entry with ' +\n 'its why; an entry that is no longer a consuming callable, or that a declaration now names, is stale.',\n run(context) {\n const { declared, findings } = readDeclarations(context, facts.clientDeclarations);\n const servers = new Map<string, { consumes: boolean; file: string; line: number }>();\n for (const file of context.files(FUNCTIONS_CODE)) {\n for (const callable of callablesOf(file)) {\n servers.set(callable.name, {\n consumes: declaresTrue(callable.options, 'consumeAppCheckToken'),\n file: file.path,\n line: lineOfNode(file, callable.node),\n });\n }\n }\n if (!servers.size)\n findings.push({\n file: '(functions)',\n detail: 'no onCall found, so the guard checks nothing',\n });\n const byName = new Map(\n declared.filter((d) => d.callable !== null).map((d) => [d.callable!, d]),\n );\n const exempt = new Set(facts.consumptionExempt.map((e) => e.callable));\n const undeclared = new Set(facts.noClientDeclaration.map((e) => e.callable));\n for (const [name, server] of servers) {\n if (!server.consumes) continue;\n const declaration = byName.get(name);\n if (!declaration) {\n if (!undeclared.has(name))\n findings.push({\n file: server.file,\n line: server.line,\n detail: `${name} consumes its token, but no client declaration names it`,\n });\n } else if (!declaration.limitedUse) {\n findings.push({\n file: declaration.file,\n line: declaration.line,\n detail: `${declaration.hook} declares ${name}, which consumes its token, without limitedUseAppCheck: true`,\n });\n }\n }\n for (const declaration of declared) {\n if (!declaration.limitedUse || declaration.callable === null) continue;\n const server = servers.get(declaration.callable);\n const where = { file: declaration.file, line: declaration.line };\n if (!server)\n findings.push({\n ...where,\n detail: `${declaration.hook} declares ${declaration.callable} limited-use, but no callable of that name exists`,\n });\n else if (exempt.has(declaration.callable))\n findings.push({\n ...where,\n detail: `${declaration.hook} declares ${declaration.callable} limited-use, but it is exempt from consumption`,\n });\n else if (!server.consumes)\n findings.push({\n ...where,\n detail: `${declaration.hook} declares ${declaration.callable} limited-use, but it does not consume its token`,\n });\n }\n for (const name of undeclared) {\n if (byName.has(name))\n findings.push({\n file: '(noClientDeclaration)',\n detail: `stale entry: a client declaration names ${name} now`,\n });\n else if (!servers.get(name)?.consumes)\n findings.push({\n file: '(noClientDeclaration)',\n detail: `stale entry: ${name} is not a consuming callable`,\n });\n }\n return findings;\n },\n };\n return [posture, client];\n },\n};\n\nexport interface AdminActionSurfaceFacts {\n adminAuth: { call: string; option: string };\n adminCheckers: readonly string[];\n checkerReaders: readonly Reviewed[];\n adminDeclarations: CallableDeclarationFacts;\n clientDeclarations: CallableDeclarationFacts;\n claimKeys: readonly string[];\n adminHooks: readonly string[];\n adminAreaRoots: readonly string[];\n affordanceOwner: string;\n reviewed: ReadonlyArray<{ path: string; symbol?: string; why: string }>;\n importAliases: Readonly<Record<string, string>>;\n appServerZone: ServerZone;\n}\n\nconst APP_CLIENT_CODE: Scope = { roots: ['app'], kinds: ['code'], tests: false };\n\nfunction authCallsIn(root: ts.Node, adminAuth: AdminActionSurfaceFacts['adminAuth']) {\n const calls: Array<{ admin: boolean }> = [];\n forEachNode(root, (node) => {\n if (!ts.isCallExpression(node) || calleeName(node) !== adminAuth.call) return;\n calls.push({\n admin: node.arguments.some(\n (arg) =>\n ts.isObjectLiteralExpression(arg) &&\n arg.properties.some(\n (p) =>\n p.name?.getText().replace(/^['\"]|['\"]$/g, '') === adminAuth.option &&\n !(ts.isPropertyAssignment(p) && isOffLiteral(p.initializer)),\n ),\n ),\n });\n });\n return calls;\n}\n\nconst isOffLiteral = (value: ts.Expression): boolean =>\n value.kind === ts.SyntaxKind.FalseKeyword ||\n value.kind === ts.SyntaxKind.NullKeyword ||\n (ts.isIdentifier(value) && value.text === 'undefined');\n\nexport function adminOnlyCallables(\n file: FileView,\n adminAuth: AdminActionSurfaceFacts['adminAuth'],\n): string[] {\n const moduleCalls = authCallsIn(file.sourceFile, adminAuth);\n return callablesOf(file)\n .filter((callable) => {\n const own = authCallsIn(callable.node, adminAuth);\n const calls = own.length ? own : moduleCalls;\n return calls.length > 0 && calls.every((c) => c.admin);\n })\n .map((callable) => callable.name);\n}\n\ninterface ClientAdminUse {\n index: number;\n symbol: string;\n detail: string;\n}\n\nexport function clientAdminUses(\n file: FileView,\n facts: Pick<AdminActionSurfaceFacts, 'claimKeys' | 'adminHooks'>,\n declarationModuleOf: (spec: string) => string | null,\n areaModuleOf: (spec: string) => string | null = () => null,\n): ClientAdminUse[] {\n const out: ClientAdminUse[] = [];\n const keys = new RegExp(`\\\\b(${facts.claimKeys.map(escapeRegExp).join('|')})\\\\b`);\n for (const hit of adminClaimMatcher(facts.claimKeys)(file))\n out.push({\n index: hit.index,\n symbol: keys.exec(hit.detail ?? '')?.[1] ?? '',\n detail: `reads the admin claim (${hit.detail})`,\n });\n const hooks = new Set(facts.adminHooks);\n for (const site of moduleImports(file.sourceFile, MODULE_LOADS)) {\n const index = site.node.getStart(file.sourceFile);\n const module = declarationModuleOf(site.spec);\n if (module) {\n const names = site.named.map((n) => n.imported);\n for (const symbol of names.length ? names : ['*'])\n out.push({\n index,\n symbol,\n detail: `imports ${symbol} from the admin declarations ${module}`,\n });\n continue;\n }\n const area = site.typeOnly ? null : areaModuleOf(site.spec);\n if (area) {\n const names = site.named.filter((n) => !n.typeOnly).map((n) => n.imported);\n for (const symbol of site.named.length ? names : ['*'])\n out.push({\n index,\n symbol,\n detail: `imports ${symbol} from the admin area ${area}`,\n });\n continue;\n }\n for (const name of site.named)\n if (hooks.has(name.imported))\n out.push({\n index,\n symbol: name.imported,\n detail: `imports the admin hook ${name.imported}`,\n });\n }\n return out.sort((a, b) => a.index - b.index);\n}\n\nfunction adminAreaProblems(facts: AdminActionSurfaceFacts | undefined, problems: string[]): void {\n if (!Array.isArray(facts?.adminAreaRoots) || !facts.adminAreaRoots.length)\n problems.push('adminAreaRoots is missing');\n else facts.adminAreaRoots.forEach((r, i) => pathProblem(r, `adminAreaRoots[${i}]`, problems));\n pathProblem(facts?.affordanceOwner, 'affordanceOwner', problems);\n reviewedProblems(facts?.reviewed, 'reviewed', problems, {\n id: (e) =>\n typeof e.path === 'string' ? `${e.path}${isText(e.symbol) ? ` ${e.symbol}` : ''}` : undefined,\n extra(entry, label) {\n if (entry.symbol !== undefined && !isText(entry.symbol))\n problems.push(`${label}'s symbol is empty`);\n },\n });\n}\n\nexport const adminActionSurfaceGuard: GenericGuardDefinition<AdminActionSurfaceFacts> = {\n id: 'adminActionSurface',\n absentWhen: 'the app has no admin actions',\n factProblems(facts) {\n const problems: string[] = [];\n if (objectProblem(facts?.adminAuth, 'adminAuth', problems)) {\n textProblem(facts.adminAuth.call, 'adminAuth.call', problems);\n textProblem(facts.adminAuth.option, 'adminAuth.option', problems);\n }\n namesProblem(facts?.adminCheckers, 'adminCheckers', problems);\n reviewedProblems(facts?.checkerReaders, 'checkerReaders', problems);\n declarationFactProblems(facts?.adminDeclarations, 'adminDeclarations', problems);\n declarationFactProblems(facts?.clientDeclarations, 'clientDeclarations', problems);\n namesProblem(facts?.claimKeys, 'claimKeys', problems);\n namesProblem(facts?.adminHooks, 'adminHooks', problems, { nonEmpty: false });\n adminAreaProblems(facts, problems);\n objectProblem(facts?.importAliases, 'importAliases', problems);\n serverZoneProblems(facts?.appServerZone, 'appServerZone', problems);\n return problems;\n },\n build(facts) {\n const declarationModules = new Set(facts.adminDeclarations.modules);\n const probePath = `${facts.affordanceOwner.slice(0, facts.affordanceOwner.lastIndexOf('/') + 1)}probe.tsx`;\n return [\n {\n title: 'admin actions outside the admin area go through the admin-actions affordance',\n description:\n `The admin-only callables are every callable whose ${facts.adminAuth.call} calls all carry ` +\n `${facts.adminAuth.option}, read from the Functions source each run. Inside a callable module, admin standing ` +\n `is checked only through that auth call: ${facts.adminCheckers.join(', ')} is called only by the reviewed ` +\n `readers. ${facts.adminDeclarations.modules.join(', ')} declares only admin-only callables, and every admin-only ` +\n `callable the client declares (${facts.clientDeclarations.modules.join(', ')}) is declared there; one with no ` +\n `client declaration has no client caller. Outside the admin area (${facts.adminAreaRoots.join(', ')}) and the ` +\n `admin-actions affordance (${facts.affordanceOwner}), client code never reads the admin claim, imports an admin ` +\n 'declaration, imports a module of the admin area, or imports an admin hook: an admin action there goes through ' +\n 'the affordance, and any other admin-standing read is a ' +\n 'reviewed entry ({ path, symbol?, why }). A reviewed reader or entry that no longer matches is stale.',\n samples: {\n flags: [\n { path: probePath, text: `if (claims?.${facts.claimKeys[0]}) show();` },\n ...facts.adminHooks\n .slice(0, 1)\n .map((hook) => ({ path: probePath, text: `import { ${hook} } from './hooks';` })),\n ],\n passes: [\n { path: probePath, text: `const label = '${facts.claimKeys[0]}';` },\n { path: probePath, text: \"import { useRows } from './hooks';\" },\n ],\n probe: (view) => clientAdminUses(view, facts, () => null),\n },\n run(context) {\n const findings: Finding[] = [];\n const adminCallables = new Map<string, { file: string; line: number }>();\n const readers = new Map(facts.checkerReaders.map((r) => [r.path, false]));\n const checkers = new Set(facts.adminCheckers);\n for (const file of context.files(FUNCTIONS_CODE)) {\n const callables = callablesOf(file);\n if (!callables.length) continue;\n for (const name of adminOnlyCallables(file, facts.adminAuth)) {\n const callable = callables.find((c) => c.name === name)!;\n adminCallables.set(name, { file: file.path, line: lineOfNode(file, callable.node) });\n }\n forEachNode(file.sourceFile, (node) => {\n if (!ts.isCallExpression(node)) return;\n const name = calleeName(node);\n if (!name || !checkers.has(name)) return;\n if (readers.has(file.path)) readers.set(file.path, true);\n else\n findings.push({\n file: file.path,\n line: lineOfNode(file, node),\n detail: `a callable module checks admin standing through ${name} instead of its ${facts.adminAuth.call}`,\n });\n });\n }\n for (const [path, used] of readers)\n if (!used)\n findings.push({\n file: path,\n detail: 'stale reader: it no longer calls an admin checker in a callable module',\n });\n if (!adminCallables.size)\n findings.push({\n file: '(functions)',\n detail: `no callable asks ${facts.adminAuth.call} for ${facts.adminAuth.option}, so no admin-only callable was found`,\n });\n\n const { declared, findings: declarationFindings } = readDeclarations(\n context,\n facts.adminDeclarations,\n );\n findings.push(...declarationFindings);\n const clientRead = readDeclarations(context, {\n ...facts.clientDeclarations,\n modules: facts.clientDeclarations.modules.filter((m) => !declarationModules.has(m)),\n });\n findings.push(...clientRead.findings);\n const clientDeclared = new Set(\n [...declared, ...clientRead.declared]\n .map((d) => d.callable)\n .filter((c): c is string => c !== null),\n );\n const declaredNames = new Set<string>();\n for (const d of declared) {\n if (d.callable === null) continue;\n declaredNames.add(d.callable);\n if (!adminCallables.has(d.callable))\n findings.push({\n file: d.file,\n line: d.line,\n detail: `${d.hook} declares ${d.callable}, which is not an admin-only callable`,\n });\n }\n for (const [name, where] of adminCallables)\n if (clientDeclared.has(name) && !declaredNames.has(name))\n findings.push({\n ...where,\n detail: `${name} is admin-only, but the client declares it outside ${facts.adminDeclarations.modules.join(', ')}`,\n });\n\n for (const root of facts.adminAreaRoots)\n if (!context.reader.exists(root))\n findings.push({ file: root, detail: 'stale admin-area root: it no longer exists' });\n const ownerExists = context.reader.exists(facts.affordanceOwner);\n if (!ownerExists)\n findings.push({\n file: facts.affordanceOwner,\n detail: 'the admin-actions affordance no longer exists',\n });\n const aliases = aliasList(facts.importAliases);\n const reviewedKey = (e: { path: string; symbol?: string }) =>\n `${e.path}${e.symbol ? ` ${e.symbol}` : ''}`;\n const reviewedSeen = new Set<string>();\n let ownerHolds = false;\n for (const file of context.files(APP_CLIENT_CODE)) {\n if (inServerZone(file, facts.appServerZone)) continue;\n if (facts.adminAreaRoots.some((root) => isUnder(file.path, root))) continue;\n const resolve = (spec: string) =>\n resolveSpecifier(context.reader, file.path, spec, aliases);\n const uses = clientAdminUses(\n file,\n facts,\n (spec) => {\n const resolved = resolve(spec);\n return declarationModules.has(resolved) ? resolved : null;\n },\n (spec) => {\n const resolved = resolve(spec);\n return facts.adminAreaRoots.some((root) => isUnder(resolved, root))\n ? resolved\n : null;\n },\n );\n if (file.path === facts.affordanceOwner) {\n ownerHolds ||= uses.length > 0;\n continue;\n }\n for (const use of uses) {\n const entry = facts.reviewed.find(\n (e) => e.path === file.path && (e.symbol === undefined || e.symbol === use.symbol),\n );\n if (entry) reviewedSeen.add(reviewedKey(entry));\n else\n findings.push({\n file: file.path,\n line: file.lineOf(use.index),\n detail: `outside the admin area: ${use.detail}`,\n });\n }\n }\n if (ownerExists && !ownerHolds)\n findings.push({\n file: facts.affordanceOwner,\n detail:\n 'stale affordance owner: it reads no admin standing and imports no admin declaration or hook',\n });\n for (const entry of facts.reviewed)\n if (!reviewedSeen.has(reviewedKey(entry)))\n findings.push({\n file: entry.path,\n detail: `stale entry: it no longer reads admin standing${entry.symbol ? ` through ${entry.symbol}` : ''}`,\n });\n return findings;\n },\n },\n ];\n },\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"read-state-branches.d.ts","sourceRoot":"","sources":["../../../src/modules/frontend-reads/read-state-branches.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACzE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAqB,KAAK,cAAc,EAAE,KAAK,GAAG,EAAE,MAAM,wBAAwB,CAAC;AAa1F,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,MAAM,EAAE;QACN,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;QACxB,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;QAC3B,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;QACnC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;KAC5B,CAAC;IACF,UAAU,EAAE;QACV,eAAe,EAAE,SAAS,cAAc,EAAE,CAAC;QAC3C,qBAAqB,EAAE,SAAS,cAAc,EAAE,CAAC;KAClD,CAAC;CACH;AAED,KAAK,MAAM,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;AAC7C,KAAK,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAE3D,UAAU,OAAO;IACf,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,QAAQ,CAAC;IACnB,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC;CACrB;AAyDD,eAAO,MAAM,QAAQ,GAAI,MAAM,MAAM,KAAG,MAA0D,CAAC;AAEnG,wBAAgB,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,EAAE,CA6FlE;AAkFD,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,GAAG,EAAE,CAkBlF;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,GAAG,EAAE,CAgB3E;AAED,eAAO,MAAM,sBAAsB,EAAE,sBAAsB,CAAC,oBAAoB,CAkH/E,CAAC"}
1
+ {"version":3,"file":"read-state-branches.d.ts","sourceRoot":"","sources":["../../../src/modules/frontend-reads/read-state-branches.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACzE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAqB,KAAK,cAAc,EAAE,KAAK,GAAG,EAAE,MAAM,wBAAwB,CAAC;AAa1F,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,MAAM,EAAE;QACN,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;QACxB,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;QAC3B,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;QACnC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;KAC5B,CAAC;IACF,UAAU,EAAE;QACV,eAAe,EAAE,SAAS,cAAc,EAAE,CAAC;QAC3C,qBAAqB,EAAE,SAAS,cAAc,EAAE,CAAC;KAClD,CAAC;CACH;AAED,KAAK,MAAM,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;AAC7C,KAAK,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAE3D,UAAU,OAAO;IACf,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,QAAQ,CAAC;IACnB,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC;CACrB;AAyDD,eAAO,MAAM,QAAQ,GAAI,MAAM,MAAM,KAAG,MAA0D,CAAC;AAEnG,wBAAgB,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,EAAE,CAmGlE;AAyGD,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,GAAG,EAAE,CAkBlF;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,GAAG,EAAE,CAgB3E;AAED,eAAO,MAAM,sBAAsB,EAAE,sBAAsB,CAAC,oBAAoB,CAkH/E,CAAC"}
@@ -142,8 +142,13 @@ export function readRefs(file, fields) {
142
142
  ts.isShorthandPropertyAssignment(parent) ||
143
143
  ts.isJsxAttribute(parent);
144
144
  const binding = isName ? undefined : bindingOf(node);
145
+ const passedWhole = ts.isJsxExpression(parent) &&
146
+ ts.isJsxAttribute(parent.parent) &&
147
+ parent.expression === node;
145
148
  if (binding?.kind === 'field' && !(binding.category === 'carrier' && isReceiver(node)))
146
149
  refs.push({ read: binding.read, category: binding.category, node });
150
+ else if (binding?.kind === 'hook' && passedWhole)
151
+ refs.push({ read: binding.read, category: 'carrier', node });
147
152
  else if (binding?.kind === 'retry' && !isReceiver(node))
148
153
  refs.push({ read: ownerOf(node), category: 'carrier', node });
149
154
  }
@@ -181,8 +186,26 @@ function noDataCheck(node) {
181
186
  }
182
187
  return null;
183
188
  }
189
+ const isNullish = (node) => node.kind === ts.SyntaxKind.NullKeyword || (ts.isIdentifier(node) && node.text === 'undefined');
190
+ function failureTest(node) {
191
+ let at = outerParens(node);
192
+ let present = true;
193
+ const parent = at.parent;
194
+ if (ts.isBinaryExpression(parent)) {
195
+ const other = unwrapped(parent.left === at ? parent.right : parent.left);
196
+ const op = parent.operatorToken.kind;
197
+ const absentWhenEqual = op === ts.SyntaxKind.EqualsEqualsEqualsToken || op === ts.SyntaxKind.EqualsEqualsToken;
198
+ const presentWhenUnequal = op === ts.SyntaxKind.ExclamationEqualsEqualsToken ||
199
+ op === ts.SyntaxKind.ExclamationEqualsToken;
200
+ if (isNullish(other) && (absentWhenEqual || presentWhenUnequal)) {
201
+ at = parent;
202
+ present = presentWhenUnequal;
203
+ }
204
+ }
205
+ return { at, present: isNegated(at) ? !present : present };
206
+ }
184
207
  function conjoinedNoData(failure, inside) {
185
- const top = chainTop(failure.node);
208
+ const top = chainTop(failureTest(failure.node).at);
186
209
  return inside.some((r) => {
187
210
  if (r.category !== 'data' || r.read !== failure.read)
188
211
  return false;
@@ -226,7 +249,7 @@ export function failureBranchesWithoutNoData(file, fields) {
226
249
  const hits = [];
227
250
  for (const condition of replacingConditions(file)) {
228
251
  const inside = refs.filter((r) => within(r.node, condition));
229
- const failures = inside.filter((r) => r.category === 'failure' && !isNegated(r.node));
252
+ const failures = inside.filter((r) => r.category === 'failure' && failureTest(r.node).present);
230
253
  const reported = new Set();
231
254
  for (const failure of failures) {
232
255
  if (reported.has(failure.read))
@@ -1 +1 @@
1
- {"version":3,"file":"read-state-branches.js","sourceRoot":"","sources":["../../../src/modules/frontend-reads/read-state-branches.ts"],"names":[],"mappings":"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","sourcesContent":["import ts from 'typescript';\nimport type { GenericGuardDefinition } from '../../node/suite/config.js';\nimport type { FileView } from '../../reader/view.js';\nimport { reviewedAllowlist, type AllowlistEntry, type Hit } from '../../shapes/shapes.js';\nimport { allowlistProblems, objectProblem } from '../../support/facts.js';\nimport { isUnder } from '../../support/text.js';\nimport {\n APP_CODE,\n filesUnder,\n identifierListProblem,\n isHookName,\n pathListProblem,\n} from './shared.js';\n\nconst RETRY_STATE_HELPERS = new Set(['useReadRetryState']);\n\nexport interface ReadStateBranchFacts {\n surfaceTrees: readonly string[];\n fields: {\n data: readonly string[];\n failure: readonly string[];\n failureCarriers: readonly string[];\n loading: readonly string[];\n };\n exceptions: {\n failureBranches: readonly AllowlistEntry[];\n loadingWithoutFailure: readonly AllowlistEntry[];\n };\n}\n\ntype Fields = ReadStateBranchFacts['fields'];\ntype Category = 'data' | 'failure' | 'carrier' | 'loading';\n\ninterface ReadRef {\n read: string;\n category: Category;\n node: ts.Expression;\n}\n\nfunction categoryOf(name: string, fields: Fields): Category | null {\n if (fields.data.includes(name)) return 'data';\n if (fields.failure.includes(name)) return 'failure';\n if (fields.failureCarriers.includes(name)) return 'carrier';\n if (fields.loading.includes(name)) return 'loading';\n return null;\n}\n\nconst unwrapped = (node: ts.Expression): ts.Expression => {\n let e = node;\n while (ts.isParenthesizedExpression(e) || ts.isNonNullExpression(e)) e = e.expression;\n return e;\n};\n\nfunction bindingFor(name: ts.BindingName, text: string): ts.Node | null {\n if (ts.isIdentifier(name)) return name.text === text ? name.parent : null;\n for (const el of name.elements) {\n if (ts.isOmittedExpression(el)) continue;\n const hit = bindingFor(el.name, text);\n if (hit) return hit;\n }\n return null;\n}\n\nfunction declarationOf(id: ts.Identifier): ts.Node | null {\n for (let scope: ts.Node | undefined = id.parent; scope; scope = scope.parent) {\n if (ts.isFunctionLike(scope))\n for (const parameter of scope.parameters) {\n const hit = bindingFor(parameter.name, id.text);\n if (hit) return hit;\n }\n const statements =\n ts.isBlock(scope) ||\n ts.isSourceFile(scope) ||\n ts.isModuleBlock(scope) ||\n ts.isCaseClause(scope) ||\n ts.isDefaultClause(scope)\n ? scope.statements\n : null;\n for (const statement of statements ?? []) {\n if (!ts.isVariableStatement(statement)) continue;\n for (const d of statement.declarationList.declarations) {\n const hit = bindingFor(d.name, id.text);\n if (hit) return hit;\n }\n }\n }\n return null;\n}\n\ntype Binding =\n | { kind: 'hook'; read: string }\n | { kind: 'retry'; source: ts.Expression }\n | { kind: 'field'; read: string; category: Category };\n\nexport const readName = (read: string): string => read.replace(/@\\d+$/, '()').replace(/#\\d+$/, '');\n\nexport function readRefs(file: FileView, fields: Fields): ReadRef[] {\n const sf = file.sourceFile;\n const bindings = new Map<ts.Node, Binding>();\n const visitBindings = (node: ts.Node): void => {\n if (ts.isVariableDeclaration(node) && node.initializer) {\n const init = unwrapped(node.initializer);\n if (ts.isCallExpression(init)) {\n const callee = init.expression.getText(sf);\n if (ts.isObjectBindingPattern(node.name) && isHookName(callee)) {\n const read = `${callee}@${node.getStart(sf)}`;\n for (const el of node.name.elements) {\n if (el.dotDotDotToken || !ts.isIdentifier(el.name)) continue;\n const category = categoryOf((el.propertyName ?? el.name).getText(sf), fields);\n if (category) bindings.set(el, { kind: 'field', read, category });\n }\n } else if (\n ts.isIdentifier(node.name) &&\n RETRY_STATE_HELPERS.has(callee) &&\n init.arguments[0]\n ) {\n bindings.set(node, { kind: 'retry', source: init.arguments[0] });\n } else if (ts.isIdentifier(node.name) && isHookName(callee)) {\n bindings.set(node, { kind: 'hook', read: `${node.name.text}#${node.getStart(sf)}` });\n }\n }\n }\n ts.forEachChild(node, visitBindings);\n };\n visitBindings(sf);\n\n const bindingOf = (id: ts.Identifier): Binding | undefined => {\n const declaration = declarationOf(id);\n return declaration ? bindings.get(declaration) : undefined;\n };\n\n const ownerOf = (receiver: ts.Expression, depth = 0): string => {\n const r = unwrapped(receiver);\n if (ts.isIdentifier(r)) {\n const binding = bindingOf(r);\n if (binding?.kind === 'hook' || binding?.kind === 'field') return binding.read;\n if (binding?.kind === 'retry' && depth < 8) return ownerOf(binding.source, depth + 1);\n return r.text;\n }\n if (ts.isPropertyAccessExpression(r) && fields.failureCarriers.includes(r.name.text))\n return ownerOf(r.expression, depth);\n return r.getText(sf);\n };\n\n const isRead = (receiver: ts.Expression): boolean => {\n const r = unwrapped(receiver);\n if (ts.isIdentifier(r)) {\n const binding = bindingOf(r);\n return (\n binding?.kind === 'hook' ||\n binding?.kind === 'retry' ||\n (binding?.kind === 'field' && binding.category === 'carrier')\n );\n }\n return ts.isPropertyAccessExpression(r) && fields.failureCarriers.includes(r.name.text)\n ? isRead(r.expression)\n : false;\n };\n\n const refs: ReadRef[] = [];\n const isReceiver = (node: ts.Node) =>\n ts.isPropertyAccessExpression(node.parent) && node.parent.expression === node;\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAccessExpression(node)) {\n const category = categoryOf(node.name.text, fields);\n if (category && !(category === 'carrier' && isReceiver(node)) && isRead(node.expression))\n refs.push({ read: ownerOf(node.expression), category, node });\n } else if (ts.isIdentifier(node)) {\n const parent = node.parent;\n const isName =\n (ts.isPropertyAccessExpression(parent) && parent.name === node) ||\n ((ts.isBindingElement(parent) ||\n ts.isVariableDeclaration(parent) ||\n ts.isPropertyAssignment(parent) ||\n ts.isParameter(parent)) &&\n parent.name === node) ||\n (ts.isBindingElement(parent) && parent.propertyName === node) ||\n ts.isShorthandPropertyAssignment(parent) ||\n ts.isJsxAttribute(parent);\n const binding = isName ? undefined : bindingOf(node);\n if (binding?.kind === 'field' && !(binding.category === 'carrier' && isReceiver(node)))\n refs.push({ read: binding.read, category: binding.category, node });\n else if (binding?.kind === 'retry' && !isReceiver(node))\n refs.push({ read: ownerOf(node), category: 'carrier', node });\n }\n ts.forEachChild(node, visit);\n };\n visit(sf);\n return refs;\n}\n\nconst within = (node: ts.Node, root: ts.Node) =>\n node.getStart() >= root.getStart() && node.getEnd() <= root.getEnd();\n\nconst isNot = (node: ts.Node): node is ts.PrefixUnaryExpression =>\n ts.isPrefixUnaryExpression(node) && node.operator === ts.SyntaxKind.ExclamationToken;\n\nconst isAnd = (node: ts.Node): node is ts.BinaryExpression =>\n ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken;\n\nfunction outerParens(node: ts.Node): ts.Node {\n let at = node;\n while (ts.isParenthesizedExpression(at.parent) || ts.isNonNullExpression(at.parent))\n at = at.parent;\n return at;\n}\n\nfunction chainTop(node: ts.Node): ts.Node {\n let at = outerParens(node);\n while (isAnd(at.parent)) at = outerParens(at.parent);\n return at;\n}\n\nfunction noDataCheck(node: ts.Expression): ts.Node | null {\n const at = outerParens(node);\n const parent = at.parent;\n if (isNot(parent)) return isNot(outerParens(parent).parent) ? null : parent;\n if (\n ts.isBinaryExpression(parent) &&\n [ts.SyntaxKind.EqualsEqualsEqualsToken, ts.SyntaxKind.EqualsEqualsToken].includes(\n parent.operatorToken.kind,\n )\n ) {\n const other = unwrapped(parent.left === at ? parent.right : parent.left);\n const absent =\n other.kind === ts.SyntaxKind.NullKeyword ||\n (ts.isIdentifier(other) && other.text === 'undefined');\n return absent ? parent : null;\n }\n return null;\n}\n\nfunction conjoinedNoData(failure: ReadRef, inside: readonly ReadRef[]): boolean {\n const top = chainTop(failure.node);\n return inside.some((r) => {\n if (r.category !== 'data' || r.read !== failure.read) return false;\n const check = noDataCheck(r.node);\n return !!check && isAnd(outerParens(check).parent) && chainTop(check) === top;\n });\n}\n\nfunction isNegated(node: ts.Expression): boolean {\n let at: ts.Node = node;\n while (ts.isParenthesizedExpression(at.parent)) at = at.parent;\n return (\n ts.isPrefixUnaryExpression(at.parent) && at.parent.operator === ts.SyntaxKind.ExclamationToken\n );\n}\n\nconst returns = (statement: ts.Statement): boolean => {\n let found = false;\n const visit = (node: ts.Node): void => {\n if (found || ts.isFunctionLike(node)) return;\n if (ts.isReturnStatement(node)) found = true;\n else ts.forEachChild(node, visit);\n };\n visit(statement);\n return found;\n};\n\nfunction replacingConditions(file: FileView): ts.Expression[] {\n const out: ts.Expression[] = [];\n const visit = (node: ts.Node): void => {\n if (ts.isConditionalExpression(node)) out.push(node.condition);\n else if (ts.isIfStatement(node) && returns(node.thenStatement)) out.push(node.expression);\n ts.forEachChild(node, visit);\n };\n visit(file.sourceFile);\n return out;\n}\n\nexport function failureBranchesWithoutNoData(file: FileView, fields: Fields): Hit[] {\n const refs = readRefs(file, fields);\n const hits: Hit[] = [];\n for (const condition of replacingConditions(file)) {\n const inside = refs.filter((r) => within(r.node, condition));\n const failures = inside.filter((r) => r.category === 'failure' && !isNegated(r.node));\n const reported = new Set<string>();\n for (const failure of failures) {\n if (reported.has(failure.read)) continue;\n if (conjoinedNoData(failure, inside)) continue;\n reported.add(failure.read);\n hits.push({\n index: failure.node.getStart(file.sourceFile),\n detail: `${failure.node.getText(file.sourceFile)} branches without checking that ${readName(failure.read)} holds no answer`,\n });\n }\n }\n return hits.sort((a, b) => a.index - b.index);\n}\n\nexport function loadingWithoutFailure(file: FileView, fields: Fields): Hit[] {\n const refs = readRefs(file, fields);\n const failing = new Set(\n refs.filter((r) => r.category === 'failure' || r.category === 'carrier').map((r) => r.read),\n );\n const hits: Hit[] = [];\n const reported = new Set<string>();\n for (const ref of refs) {\n if (ref.category !== 'loading' || failing.has(ref.read) || reported.has(ref.read)) continue;\n reported.add(ref.read);\n hits.push({\n index: ref.node.getStart(file.sourceFile),\n detail: `${ref.node.getText(file.sourceFile)} is used, but ${readName(ref.read)}'s failure never is`,\n });\n }\n return hits.sort((a, b) => a.index - b.index);\n}\n\nexport const readStateBranchesGuard: GenericGuardDefinition<ReadStateBranchFacts> = {\n id: 'readStateBranches',\n absentWhen: false,\n factProblems(facts) {\n const problems: string[] = [];\n pathListProblem(facts?.surfaceTrees, 'surfaceTrees', problems);\n if (objectProblem(facts?.fields, 'fields', problems)) {\n identifierListProblem(facts.fields.data, 'fields.data', problems, { nonEmpty: true });\n identifierListProblem(facts.fields.failure, 'fields.failure', problems, { nonEmpty: true });\n identifierListProblem(facts.fields.failureCarriers, 'fields.failureCarriers', problems, {\n nonEmpty: false,\n });\n identifierListProblem(facts.fields.loading, 'fields.loading', problems, { nonEmpty: true });\n const all = [\n ...(facts.fields.data ?? []),\n ...(facts.fields.failure ?? []),\n ...(facts.fields.failureCarriers ?? []),\n ...(facts.fields.loading ?? []),\n ];\n const seen = new Set<string>();\n for (const name of all) {\n if (seen.has(name)) problems.push(`fields names ${name} in two roles`);\n seen.add(name);\n }\n }\n if (objectProblem(facts?.exceptions, 'exceptions', problems)) {\n allowlistProblems(facts.exceptions.failureBranches, 'exceptions.failureBranches', problems);\n allowlistProblems(\n facts.exceptions.loadingWithoutFailure,\n 'exceptions.loadingWithoutFailure',\n problems,\n );\n }\n return problems;\n },\n build(facts) {\n const { fields } = facts;\n const inTrees = (file: FileView) => facts.surfaceTrees.some((tree) => isUnder(file.path, tree));\n const sample = `${facts.surfaceTrees[0]}/sample.tsx`;\n const [data] = fields.data;\n const [failure] = fields.failure;\n const [loading] = fields.loading;\n const failureBranch = reviewedAllowlist({\n title: 'a failure branch that replaces a read also checks that nothing answered',\n description:\n `In a render surface (${facts.surfaceTrees.join(', ')}), a branch that swaps the content for the failure — a ` +\n `ternary, or an if that returns — on a read's failure (${[...fields.failure, ...fields.failureCarriers].join(' / ')}) ` +\n `is conjoined with a check that the same read holds no answer (!${fields.data.join(' / !')}, or a compare with ` +\n 'null or undefined). A read that answered and then fails keeps its answer: the content, and any editor open in ' +\n 'it, stays on screen with the failure inline, and only a failure with nothing answered replaces it. A reviewed ' +\n 'exception names the file and its why.',\n scope: APP_CODE,\n match: (file) => (inTrees(file) ? failureBranchesWithoutNoData(file, fields) : []),\n allowlist: facts.exceptions.failureBranches,\n samples: {\n flags: [\n {\n path: sample,\n text: `const { ${data}, ${failure} } = useRows();\\nreturn ${failure} ? <Failed /> : <List rows={${data}} />;`,\n },\n {\n path: sample,\n text: `const rows = useRows();\\nif (rows.${failure}) return <Failed />;\\nreturn <List rows={rows.${data}} />;`,\n },\n ],\n passes: [\n {\n path: sample,\n text: `const { ${data}, ${failure} } = useRows();\\nreturn ${failure} && !${data} ? <Failed /> : <List rows={${data}} />;`,\n },\n {\n path: sample,\n text: `const rows = useRows();\\nif (rows.${failure} && rows.${data} === undefined) return <Failed />;\\nreturn <List rows={rows.${data}} />;`,\n },\n {\n path: sample,\n text: `const rows = useRows();\\nreturn <>{rows.${failure} && <InlineFailure />}<List rows={rows.${data}} /></>;`,\n },\n ],\n },\n });\n const loadingAlone = reviewedAllowlist({\n title: \"a surface that renders a read's loading state also renders its failure\",\n description:\n `A render surface (${facts.surfaceTrees.join(', ')}) that reads a read's loading state ` +\n `(${fields.loading.join(' / ')}) also reads that read's failure (${[...fields.failure, ...fields.failureCarriers].join(' / ')}). ` +\n 'A surface with a loading branch and no failure branch renders a failed read as an endless pending state or ' +\n 'as an empty answer. A reviewed exception names the file and its why.',\n scope: APP_CODE,\n match: (file) => (inTrees(file) ? loadingWithoutFailure(file, fields) : []),\n allowlist: facts.exceptions.loadingWithoutFailure,\n samples: {\n flags: [\n {\n path: sample,\n text: `const { ${data}, ${loading} } = useRows();\\nif (${loading}) return <Spinner />;\\nreturn <List rows={${data}} />;`,\n },\n ],\n passes: [\n {\n path: sample,\n text: `const { ${data}, ${loading}, ${failure} } = useRows();\\nif (${loading}) return <Spinner />;\\nif (${failure} && !${data}) return <Failed />;\\nreturn <List rows={${data}} />;`,\n },\n ],\n },\n });\n const withTrees = (guard: typeof failureBranch): typeof failureBranch => ({\n ...guard,\n async run(context) {\n return [...filesUnder(context, facts.surfaceTrees).findings, ...(await guard.run(context))];\n },\n });\n return [withTrees(failureBranch), withTrees(loadingAlone)];\n },\n};\n"]}
1
+ {"version":3,"file":"read-state-branches.js","sourceRoot":"","sources":["../../../src/modules/frontend-reads/read-state-branches.ts"],"names":[],"mappings":"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","sourcesContent":["import ts from 'typescript';\nimport type { GenericGuardDefinition } from '../../node/suite/config.js';\nimport type { FileView } from '../../reader/view.js';\nimport { reviewedAllowlist, type AllowlistEntry, type Hit } from '../../shapes/shapes.js';\nimport { allowlistProblems, objectProblem } from '../../support/facts.js';\nimport { isUnder } from '../../support/text.js';\nimport {\n APP_CODE,\n filesUnder,\n identifierListProblem,\n isHookName,\n pathListProblem,\n} from './shared.js';\n\nconst RETRY_STATE_HELPERS = new Set(['useReadRetryState']);\n\nexport interface ReadStateBranchFacts {\n surfaceTrees: readonly string[];\n fields: {\n data: readonly string[];\n failure: readonly string[];\n failureCarriers: readonly string[];\n loading: readonly string[];\n };\n exceptions: {\n failureBranches: readonly AllowlistEntry[];\n loadingWithoutFailure: readonly AllowlistEntry[];\n };\n}\n\ntype Fields = ReadStateBranchFacts['fields'];\ntype Category = 'data' | 'failure' | 'carrier' | 'loading';\n\ninterface ReadRef {\n read: string;\n category: Category;\n node: ts.Expression;\n}\n\nfunction categoryOf(name: string, fields: Fields): Category | null {\n if (fields.data.includes(name)) return 'data';\n if (fields.failure.includes(name)) return 'failure';\n if (fields.failureCarriers.includes(name)) return 'carrier';\n if (fields.loading.includes(name)) return 'loading';\n return null;\n}\n\nconst unwrapped = (node: ts.Expression): ts.Expression => {\n let e = node;\n while (ts.isParenthesizedExpression(e) || ts.isNonNullExpression(e)) e = e.expression;\n return e;\n};\n\nfunction bindingFor(name: ts.BindingName, text: string): ts.Node | null {\n if (ts.isIdentifier(name)) return name.text === text ? name.parent : null;\n for (const el of name.elements) {\n if (ts.isOmittedExpression(el)) continue;\n const hit = bindingFor(el.name, text);\n if (hit) return hit;\n }\n return null;\n}\n\nfunction declarationOf(id: ts.Identifier): ts.Node | null {\n for (let scope: ts.Node | undefined = id.parent; scope; scope = scope.parent) {\n if (ts.isFunctionLike(scope))\n for (const parameter of scope.parameters) {\n const hit = bindingFor(parameter.name, id.text);\n if (hit) return hit;\n }\n const statements =\n ts.isBlock(scope) ||\n ts.isSourceFile(scope) ||\n ts.isModuleBlock(scope) ||\n ts.isCaseClause(scope) ||\n ts.isDefaultClause(scope)\n ? scope.statements\n : null;\n for (const statement of statements ?? []) {\n if (!ts.isVariableStatement(statement)) continue;\n for (const d of statement.declarationList.declarations) {\n const hit = bindingFor(d.name, id.text);\n if (hit) return hit;\n }\n }\n }\n return null;\n}\n\ntype Binding =\n | { kind: 'hook'; read: string }\n | { kind: 'retry'; source: ts.Expression }\n | { kind: 'field'; read: string; category: Category };\n\nexport const readName = (read: string): string => read.replace(/@\\d+$/, '()').replace(/#\\d+$/, '');\n\nexport function readRefs(file: FileView, fields: Fields): ReadRef[] {\n const sf = file.sourceFile;\n const bindings = new Map<ts.Node, Binding>();\n const visitBindings = (node: ts.Node): void => {\n if (ts.isVariableDeclaration(node) && node.initializer) {\n const init = unwrapped(node.initializer);\n if (ts.isCallExpression(init)) {\n const callee = init.expression.getText(sf);\n if (ts.isObjectBindingPattern(node.name) && isHookName(callee)) {\n const read = `${callee}@${node.getStart(sf)}`;\n for (const el of node.name.elements) {\n if (el.dotDotDotToken || !ts.isIdentifier(el.name)) continue;\n const category = categoryOf((el.propertyName ?? el.name).getText(sf), fields);\n if (category) bindings.set(el, { kind: 'field', read, category });\n }\n } else if (\n ts.isIdentifier(node.name) &&\n RETRY_STATE_HELPERS.has(callee) &&\n init.arguments[0]\n ) {\n bindings.set(node, { kind: 'retry', source: init.arguments[0] });\n } else if (ts.isIdentifier(node.name) && isHookName(callee)) {\n bindings.set(node, { kind: 'hook', read: `${node.name.text}#${node.getStart(sf)}` });\n }\n }\n }\n ts.forEachChild(node, visitBindings);\n };\n visitBindings(sf);\n\n const bindingOf = (id: ts.Identifier): Binding | undefined => {\n const declaration = declarationOf(id);\n return declaration ? bindings.get(declaration) : undefined;\n };\n\n const ownerOf = (receiver: ts.Expression, depth = 0): string => {\n const r = unwrapped(receiver);\n if (ts.isIdentifier(r)) {\n const binding = bindingOf(r);\n if (binding?.kind === 'hook' || binding?.kind === 'field') return binding.read;\n if (binding?.kind === 'retry' && depth < 8) return ownerOf(binding.source, depth + 1);\n return r.text;\n }\n if (ts.isPropertyAccessExpression(r) && fields.failureCarriers.includes(r.name.text))\n return ownerOf(r.expression, depth);\n return r.getText(sf);\n };\n\n const isRead = (receiver: ts.Expression): boolean => {\n const r = unwrapped(receiver);\n if (ts.isIdentifier(r)) {\n const binding = bindingOf(r);\n return (\n binding?.kind === 'hook' ||\n binding?.kind === 'retry' ||\n (binding?.kind === 'field' && binding.category === 'carrier')\n );\n }\n return ts.isPropertyAccessExpression(r) && fields.failureCarriers.includes(r.name.text)\n ? isRead(r.expression)\n : false;\n };\n\n const refs: ReadRef[] = [];\n const isReceiver = (node: ts.Node) =>\n ts.isPropertyAccessExpression(node.parent) && node.parent.expression === node;\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAccessExpression(node)) {\n const category = categoryOf(node.name.text, fields);\n if (category && !(category === 'carrier' && isReceiver(node)) && isRead(node.expression))\n refs.push({ read: ownerOf(node.expression), category, node });\n } else if (ts.isIdentifier(node)) {\n const parent = node.parent;\n const isName =\n (ts.isPropertyAccessExpression(parent) && parent.name === node) ||\n ((ts.isBindingElement(parent) ||\n ts.isVariableDeclaration(parent) ||\n ts.isPropertyAssignment(parent) ||\n ts.isParameter(parent)) &&\n parent.name === node) ||\n (ts.isBindingElement(parent) && parent.propertyName === node) ||\n ts.isShorthandPropertyAssignment(parent) ||\n ts.isJsxAttribute(parent);\n const binding = isName ? undefined : bindingOf(node);\n const passedWhole =\n ts.isJsxExpression(parent) &&\n ts.isJsxAttribute(parent.parent) &&\n parent.expression === node;\n if (binding?.kind === 'field' && !(binding.category === 'carrier' && isReceiver(node)))\n refs.push({ read: binding.read, category: binding.category, node });\n else if (binding?.kind === 'hook' && passedWhole)\n refs.push({ read: binding.read, category: 'carrier', node });\n else if (binding?.kind === 'retry' && !isReceiver(node))\n refs.push({ read: ownerOf(node), category: 'carrier', node });\n }\n ts.forEachChild(node, visit);\n };\n visit(sf);\n return refs;\n}\n\nconst within = (node: ts.Node, root: ts.Node) =>\n node.getStart() >= root.getStart() && node.getEnd() <= root.getEnd();\n\nconst isNot = (node: ts.Node): node is ts.PrefixUnaryExpression =>\n ts.isPrefixUnaryExpression(node) && node.operator === ts.SyntaxKind.ExclamationToken;\n\nconst isAnd = (node: ts.Node): node is ts.BinaryExpression =>\n ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken;\n\nfunction outerParens(node: ts.Node): ts.Node {\n let at = node;\n while (ts.isParenthesizedExpression(at.parent) || ts.isNonNullExpression(at.parent))\n at = at.parent;\n return at;\n}\n\nfunction chainTop(node: ts.Node): ts.Node {\n let at = outerParens(node);\n while (isAnd(at.parent)) at = outerParens(at.parent);\n return at;\n}\n\nfunction noDataCheck(node: ts.Expression): ts.Node | null {\n const at = outerParens(node);\n const parent = at.parent;\n if (isNot(parent)) return isNot(outerParens(parent).parent) ? null : parent;\n if (\n ts.isBinaryExpression(parent) &&\n [ts.SyntaxKind.EqualsEqualsEqualsToken, ts.SyntaxKind.EqualsEqualsToken].includes(\n parent.operatorToken.kind,\n )\n ) {\n const other = unwrapped(parent.left === at ? parent.right : parent.left);\n const absent =\n other.kind === ts.SyntaxKind.NullKeyword ||\n (ts.isIdentifier(other) && other.text === 'undefined');\n return absent ? parent : null;\n }\n return null;\n}\n\nconst isNullish = (node: ts.Expression): boolean =>\n node.kind === ts.SyntaxKind.NullKeyword || (ts.isIdentifier(node) && node.text === 'undefined');\n\nfunction failureTest(node: ts.Expression): { at: ts.Expression; present: boolean } {\n let at = outerParens(node) as ts.Expression;\n let present = true;\n const parent = at.parent;\n if (ts.isBinaryExpression(parent)) {\n const other = unwrapped(parent.left === at ? parent.right : parent.left);\n const op = parent.operatorToken.kind;\n const absentWhenEqual =\n op === ts.SyntaxKind.EqualsEqualsEqualsToken || op === ts.SyntaxKind.EqualsEqualsToken;\n const presentWhenUnequal =\n op === ts.SyntaxKind.ExclamationEqualsEqualsToken ||\n op === ts.SyntaxKind.ExclamationEqualsToken;\n if (isNullish(other) && (absentWhenEqual || presentWhenUnequal)) {\n at = parent;\n present = presentWhenUnequal;\n }\n }\n return { at, present: isNegated(at) ? !present : present };\n}\n\nfunction conjoinedNoData(failure: ReadRef, inside: readonly ReadRef[]): boolean {\n const top = chainTop(failureTest(failure.node).at);\n return inside.some((r) => {\n if (r.category !== 'data' || r.read !== failure.read) return false;\n const check = noDataCheck(r.node);\n return !!check && isAnd(outerParens(check).parent) && chainTop(check) === top;\n });\n}\n\nfunction isNegated(node: ts.Expression): boolean {\n let at: ts.Node = node;\n while (ts.isParenthesizedExpression(at.parent)) at = at.parent;\n return (\n ts.isPrefixUnaryExpression(at.parent) && at.parent.operator === ts.SyntaxKind.ExclamationToken\n );\n}\n\nconst returns = (statement: ts.Statement): boolean => {\n let found = false;\n const visit = (node: ts.Node): void => {\n if (found || ts.isFunctionLike(node)) return;\n if (ts.isReturnStatement(node)) found = true;\n else ts.forEachChild(node, visit);\n };\n visit(statement);\n return found;\n};\n\nfunction replacingConditions(file: FileView): ts.Expression[] {\n const out: ts.Expression[] = [];\n const visit = (node: ts.Node): void => {\n if (ts.isConditionalExpression(node)) out.push(node.condition);\n else if (ts.isIfStatement(node) && returns(node.thenStatement)) out.push(node.expression);\n ts.forEachChild(node, visit);\n };\n visit(file.sourceFile);\n return out;\n}\n\nexport function failureBranchesWithoutNoData(file: FileView, fields: Fields): Hit[] {\n const refs = readRefs(file, fields);\n const hits: Hit[] = [];\n for (const condition of replacingConditions(file)) {\n const inside = refs.filter((r) => within(r.node, condition));\n const failures = inside.filter((r) => r.category === 'failure' && failureTest(r.node).present);\n const reported = new Set<string>();\n for (const failure of failures) {\n if (reported.has(failure.read)) continue;\n if (conjoinedNoData(failure, inside)) continue;\n reported.add(failure.read);\n hits.push({\n index: failure.node.getStart(file.sourceFile),\n detail: `${failure.node.getText(file.sourceFile)} branches without checking that ${readName(failure.read)} holds no answer`,\n });\n }\n }\n return hits.sort((a, b) => a.index - b.index);\n}\n\nexport function loadingWithoutFailure(file: FileView, fields: Fields): Hit[] {\n const refs = readRefs(file, fields);\n const failing = new Set(\n refs.filter((r) => r.category === 'failure' || r.category === 'carrier').map((r) => r.read),\n );\n const hits: Hit[] = [];\n const reported = new Set<string>();\n for (const ref of refs) {\n if (ref.category !== 'loading' || failing.has(ref.read) || reported.has(ref.read)) continue;\n reported.add(ref.read);\n hits.push({\n index: ref.node.getStart(file.sourceFile),\n detail: `${ref.node.getText(file.sourceFile)} is used, but ${readName(ref.read)}'s failure never is`,\n });\n }\n return hits.sort((a, b) => a.index - b.index);\n}\n\nexport const readStateBranchesGuard: GenericGuardDefinition<ReadStateBranchFacts> = {\n id: 'readStateBranches',\n absentWhen: false,\n factProblems(facts) {\n const problems: string[] = [];\n pathListProblem(facts?.surfaceTrees, 'surfaceTrees', problems);\n if (objectProblem(facts?.fields, 'fields', problems)) {\n identifierListProblem(facts.fields.data, 'fields.data', problems, { nonEmpty: true });\n identifierListProblem(facts.fields.failure, 'fields.failure', problems, { nonEmpty: true });\n identifierListProblem(facts.fields.failureCarriers, 'fields.failureCarriers', problems, {\n nonEmpty: false,\n });\n identifierListProblem(facts.fields.loading, 'fields.loading', problems, { nonEmpty: true });\n const all = [\n ...(facts.fields.data ?? []),\n ...(facts.fields.failure ?? []),\n ...(facts.fields.failureCarriers ?? []),\n ...(facts.fields.loading ?? []),\n ];\n const seen = new Set<string>();\n for (const name of all) {\n if (seen.has(name)) problems.push(`fields names ${name} in two roles`);\n seen.add(name);\n }\n }\n if (objectProblem(facts?.exceptions, 'exceptions', problems)) {\n allowlistProblems(facts.exceptions.failureBranches, 'exceptions.failureBranches', problems);\n allowlistProblems(\n facts.exceptions.loadingWithoutFailure,\n 'exceptions.loadingWithoutFailure',\n problems,\n );\n }\n return problems;\n },\n build(facts) {\n const { fields } = facts;\n const inTrees = (file: FileView) => facts.surfaceTrees.some((tree) => isUnder(file.path, tree));\n const sample = `${facts.surfaceTrees[0]}/sample.tsx`;\n const [data] = fields.data;\n const [failure] = fields.failure;\n const [loading] = fields.loading;\n const failureBranch = reviewedAllowlist({\n title: 'a failure branch that replaces a read also checks that nothing answered',\n description:\n `In a render surface (${facts.surfaceTrees.join(', ')}), a branch that swaps the content for the failure — a ` +\n `ternary, or an if that returns — on a read's failure (${[...fields.failure, ...fields.failureCarriers].join(' / ')}) ` +\n `is conjoined with a check that the same read holds no answer (!${fields.data.join(' / !')}, or a compare with ` +\n 'null or undefined). A read that answered and then fails keeps its answer: the content, and any editor open in ' +\n 'it, stays on screen with the failure inline, and only a failure with nothing answered replaces it. A reviewed ' +\n 'exception names the file and its why.',\n scope: APP_CODE,\n match: (file) => (inTrees(file) ? failureBranchesWithoutNoData(file, fields) : []),\n allowlist: facts.exceptions.failureBranches,\n samples: {\n flags: [\n {\n path: sample,\n text: `const { ${data}, ${failure} } = useRows();\\nreturn ${failure} ? <Failed /> : <List rows={${data}} />;`,\n },\n {\n path: sample,\n text: `const rows = useRows();\\nif (rows.${failure}) return <Failed />;\\nreturn <List rows={rows.${data}} />;`,\n },\n ],\n passes: [\n {\n path: sample,\n text: `const { ${data}, ${failure} } = useRows();\\nreturn ${failure} && !${data} ? <Failed /> : <List rows={${data}} />;`,\n },\n {\n path: sample,\n text: `const rows = useRows();\\nif (rows.${failure} && rows.${data} === undefined) return <Failed />;\\nreturn <List rows={rows.${data}} />;`,\n },\n {\n path: sample,\n text: `const rows = useRows();\\nreturn <>{rows.${failure} && <InlineFailure />}<List rows={rows.${data}} /></>;`,\n },\n ],\n },\n });\n const loadingAlone = reviewedAllowlist({\n title: \"a surface that renders a read's loading state also renders its failure\",\n description:\n `A render surface (${facts.surfaceTrees.join(', ')}) that reads a read's loading state ` +\n `(${fields.loading.join(' / ')}) also reads that read's failure (${[...fields.failure, ...fields.failureCarriers].join(' / ')}). ` +\n 'A surface with a loading branch and no failure branch renders a failed read as an endless pending state or ' +\n 'as an empty answer. A reviewed exception names the file and its why.',\n scope: APP_CODE,\n match: (file) => (inTrees(file) ? loadingWithoutFailure(file, fields) : []),\n allowlist: facts.exceptions.loadingWithoutFailure,\n samples: {\n flags: [\n {\n path: sample,\n text: `const { ${data}, ${loading} } = useRows();\\nif (${loading}) return <Spinner />;\\nreturn <List rows={${data}} />;`,\n },\n ],\n passes: [\n {\n path: sample,\n text: `const { ${data}, ${loading}, ${failure} } = useRows();\\nif (${loading}) return <Spinner />;\\nif (${failure} && !${data}) return <Failed />;\\nreturn <List rows={${data}} />;`,\n },\n ],\n },\n });\n const withTrees = (guard: typeof failureBranch): typeof failureBranch => ({\n ...guard,\n async run(context) {\n return [...filesUnder(context, facts.surfaceTrees).findings, ...(await guard.run(context))];\n },\n });\n return [withTrees(failureBranch), withTrees(loadingAlone)];\n },\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttt-productions/repo-guards",
3
- "version": "0.1.17",
3
+ "version": "0.1.19",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/ttt-productions/ttt-packages.git",