pumuki 6.3.214 → 6.3.216

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.
@@ -23,6 +23,7 @@ import {
23
23
  hasSwiftForceUnwrap,
24
24
  hasSwiftGeometryReaderUsage,
25
25
  hasSwiftHardcodedUiStringUsage,
26
+ hasSwiftHardcodedSensitiveStringUsage,
26
27
  hasSwiftIconOnlyControlWithoutAccessibilityLabelUsage,
27
28
  hasSwiftLooseAssetResourceUsage,
28
29
  hasSwiftLegacyOnChangeUsage,
@@ -61,6 +62,7 @@ import {
61
62
  hasSwiftStringFormatUsage,
62
63
  hasSwiftStrongDelegateReferenceUsage,
63
64
  hasSwiftStrongSelfEscapingClosureUsage,
65
+ hasSwiftSwinjectUsage,
64
66
  hasSwiftTabItemUsage,
65
67
  hasSwiftTaskDetachedUsage,
66
68
  hasSwiftWaitForExpectationsUsage,
@@ -287,6 +289,34 @@ final class APIClient {
287
289
  assert.equal(hasSwiftCustomSingletonUsage(ignored), false);
288
290
  });
289
291
 
292
+ test('hasSwiftSwinjectUsage detecta DI de terceros y preserva DI nativa', () => {
293
+ const source = `
294
+ import Swinject
295
+
296
+ final class AppAssembly {
297
+ private let container = Container()
298
+ private let assembler = Assembler([])
299
+ }
300
+ `;
301
+ const native = `
302
+ struct AppDependencies {
303
+ let apiClient: APIClient
304
+ }
305
+
306
+ private struct DependenciesKey: EnvironmentKey {
307
+ static let defaultValue = AppDependencies(apiClient: URLSessionAPIClient())
308
+ }
309
+ `;
310
+ const ignored = `
311
+ let text = "import Swinject"
312
+ // let container = Container()
313
+ `;
314
+
315
+ assert.equal(hasSwiftSwinjectUsage(source), true);
316
+ assert.equal(hasSwiftSwinjectUsage(native), false);
317
+ assert.equal(hasSwiftSwinjectUsage(ignored), false);
318
+ });
319
+
290
320
  test('hasSwiftMassiveViewControllerResponsibilityUsage detecta ViewControllers con acceso directo a infraestructura', () => {
291
321
  const source = `
292
322
  final class CheckoutViewController: UIViewController {
@@ -397,6 +427,25 @@ logger.error("Refresh failed \\(refreshToken)")
397
427
  assert.equal(hasSwiftSensitiveLoggingUsage(structuredSafe), false);
398
428
  });
399
429
 
430
+ test('hasSwiftHardcodedSensitiveStringUsage detecta secretos hardcodeados en Swift productivo', () => {
431
+ const source = `
432
+ final class Credentials {
433
+ let apiKey = "sk_live_123456789"
434
+ private var refreshToken: String = "refresh-token-123456"
435
+ }
436
+ `;
437
+ const safe = `
438
+ final class Credentials {
439
+ let apiKey = keychain.read("api_key")
440
+ let label = "public title"
441
+ // let apiKey = "sk_live_123456789"
442
+ }
443
+ `;
444
+
445
+ assert.equal(hasSwiftHardcodedSensitiveStringUsage(source), true);
446
+ assert.equal(hasSwiftHardcodedSensitiveStringUsage(safe), false);
447
+ });
448
+
400
449
  test('detectores iOS de networking y JSON detectan Alamofire y JSONSerialization sin leer comentarios ni strings', () => {
401
450
  const source = `
402
451
  import Alamofire
@@ -528,6 +528,13 @@ export const hasSwiftCustomSingletonUsage = (source: string): boolean => {
528
528
  });
529
529
  };
530
530
 
531
+ export const hasSwiftSwinjectUsage = (source: string): boolean => {
532
+ return hasSwiftSanitizedRegexMatch(
533
+ source,
534
+ /\bimport\s+Swinject\b|\b(?:Container|Assembler)\s*\(/
535
+ );
536
+ };
537
+
531
538
  export const hasSwiftMassiveViewControllerResponsibilityUsage = (source: string): boolean => {
532
539
  const sanitized = sanitizeSwiftSourceForMultilineRegex(source);
533
540
  const viewControllerPattern =
@@ -593,6 +600,13 @@ export const hasSwiftSensitiveLoggingUsage = (source: string): boolean => {
593
600
  });
594
601
  };
595
602
 
603
+ export const hasSwiftHardcodedSensitiveStringUsage = (source: string): boolean => {
604
+ return collectSwiftRegexLines(
605
+ source,
606
+ /\b(?:(?:private|fileprivate|internal|public|open|static|class|final|lazy)\s+)*(?:let|var)\s+(?=[A-Za-z_])[A-Za-z0-9_]*(?:token|secret|password|apikey|clientsecret|privatekey|sessionid)[A-Za-z0-9_]*\s*(?::\s*String\s*)?=\s*""/i
607
+ ).length > 0;
608
+ };
609
+
596
610
  export const hasSwiftAlamofireUsage = (source: string): boolean => {
597
611
  return (
598
612
  collectSwiftRegexLines(source, /^\s*import\s+Alamofire\b/).length > 0 ||
@@ -649,11 +649,13 @@ const textDetectorRegistry: ReadonlyArray<TextDetectorRegistryEntry> = [
649
649
  { platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftStrongDelegateReferenceUsage, ruleId: 'heuristics.ios.memory.strong-delegate.ast', code: 'HEURISTICS_IOS_MEMORY_STRONG_DELEGATE_AST', message: 'AST heuristic detected a strong delegate/dataSource reference; weak delegates remain the preferred baseline to avoid retain cycles.' },
650
650
  { platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftStrongSelfEscapingClosureUsage, ruleId: 'heuristics.ios.memory.strong-self-escaping-closure.ast', code: 'HEURISTICS_IOS_MEMORY_STRONG_SELF_ESCAPING_CLOSURE_AST', message: 'AST heuristic detected strong self capture in an escaping iOS closure; weak or unowned captures remain the preferred baseline when ownership is not explicit.' },
651
651
  { platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftCustomSingletonUsage, ruleId: 'heuristics.ios.architecture.custom-singleton.ast', code: 'HEURISTICS_IOS_ARCHITECTURE_CUSTOM_SINGLETON_AST', message: 'AST heuristic detected a custom static shared singleton in iOS production code; dependency injection remains the preferred baseline for app-owned services.' },
652
+ { platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftSwinjectUsage, ruleId: 'heuristics.ios.architecture.swinject.ast', code: 'HEURISTICS_IOS_ARCHITECTURE_SWINJECT_AST', message: 'AST heuristic detected Swinject usage; manual dependency injection or SwiftUI Environment remain the preferred native baseline.' },
652
653
  { platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftMassiveViewControllerResponsibilityUsage, ruleId: 'heuristics.ios.architecture.massive-view-controller.ast', code: 'HEURISTICS_IOS_ARCHITECTURE_MASSIVE_VIEW_CONTROLLER_AST', message: 'AST heuristic detected a UIViewController with direct infrastructure/data access; move data access behind application/domain boundaries.' },
653
654
  { platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftNonIBOutletImplicitlyUnwrappedOptionalUsage, ruleId: 'heuristics.ios.safety.non-iboutlet-iuo.ast', code: 'HEURISTICS_IOS_SAFETY_NON_IBOUTLET_IUO_AST', message: 'AST heuristic detected an implicitly unwrapped optional outside IBOutlet wiring; explicit optionals or initialization guarantees remain the preferred baseline.' },
654
655
  { platform: 'ios', pathCheck: isIOSPresentationPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftMagicNumberLayoutUsage, ruleId: 'heuristics.ios.maintainability.magic-number-layout.ast', code: 'HEURISTICS_IOS_MAINTAINABILITY_MAGIC_NUMBER_LAYOUT_AST', message: 'AST heuristic detected SwiftUI layout magic numbers; named constants or design tokens remain the preferred baseline.' },
655
656
  { platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftAdHocLoggingUsage, ruleId: 'heuristics.ios.logging.adhoc-print.ast', code: 'HEURISTICS_IOS_LOGGING_ADHOC_PRINT_AST', message: 'AST heuristic detected print/debugPrint/dump/NSLog/os_log usage in iOS production code.' },
656
657
  { platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftSensitiveLoggingUsage, ruleId: 'heuristics.ios.logging.sensitive-data.ast', code: 'HEURISTICS_IOS_LOGGING_SENSITIVE_DATA_AST', message: 'AST heuristic detected sensitive data in an iOS logging call.' },
658
+ { platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftHardcodedSensitiveStringUsage, ruleId: 'heuristics.ios.security.hardcoded-sensitive-string.ast', code: 'HEURISTICS_IOS_SECURITY_HARDCODED_SENSITIVE_STRING_AST', message: 'AST heuristic detected hardcoded sensitive Swift string; Keychain, secure config or environment-specific secrets remain the preferred baseline.' },
657
659
  { platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftAlamofireUsage, ruleId: 'heuristics.ios.networking.alamofire.ast', code: 'HEURISTICS_IOS_NETWORKING_ALAMOFIRE_AST', message: 'AST heuristic detected Alamofire usage in iOS production code; URLSession remains the preferred baseline for new code.' },
658
660
  { platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftJSONSerializationUsage, ruleId: 'heuristics.ios.json.jsonserialization.ast', code: 'HEURISTICS_IOS_JSON_JSONSERIALIZATION_AST', message: 'AST heuristic detected JSONSerialization usage in iOS production code; Codable remains the preferred baseline for new code.' },
659
661
  { platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftSensitiveUserDefaultsStorageUsage, ruleId: 'heuristics.ios.security.userdefaults-sensitive-data.ast', code: 'HEURISTICS_IOS_SECURITY_USERDEFAULTS_SENSITIVE_DATA_AST', message: 'AST heuristic detected sensitive data stored in UserDefaults/AppStorage; native Keychain remains the preferred baseline for secrets.' },
@@ -238,6 +238,25 @@ export const iosRules: RuleSet = [
238
238
  code: 'HEURISTICS_IOS_ARCHITECTURE_CUSTOM_SINGLETON_AST',
239
239
  },
240
240
  },
241
+ {
242
+ id: 'heuristics.ios.architecture.swinject.ast',
243
+ description: 'Detects Swinject usage in iOS production code.',
244
+ severity: 'WARN',
245
+ platform: 'ios',
246
+ locked: true,
247
+ when: {
248
+ kind: 'Heuristic',
249
+ where: {
250
+ ruleId: 'heuristics.ios.architecture.swinject.ast',
251
+ },
252
+ },
253
+ then: {
254
+ kind: 'Finding',
255
+ message:
256
+ 'AST heuristic detected Swinject usage; manual dependency injection or SwiftUI Environment remain the preferred native baseline.',
257
+ code: 'HEURISTICS_IOS_ARCHITECTURE_SWINJECT_AST',
258
+ },
259
+ },
241
260
  {
242
261
  id: 'heuristics.ios.architecture.massive-view-controller.ast',
243
262
  description: 'Detects UIViewController classes with direct infrastructure/data access.',
@@ -331,6 +350,25 @@ export const iosRules: RuleSet = [
331
350
  code: 'HEURISTICS_IOS_LOGGING_SENSITIVE_DATA_AST',
332
351
  },
333
352
  },
353
+ {
354
+ id: 'heuristics.ios.security.hardcoded-sensitive-string.ast',
355
+ description: 'Detects hardcoded sensitive Swift string values in iOS production code.',
356
+ severity: 'WARN',
357
+ platform: 'ios',
358
+ locked: true,
359
+ when: {
360
+ kind: 'Heuristic',
361
+ where: {
362
+ ruleId: 'heuristics.ios.security.hardcoded-sensitive-string.ast',
363
+ },
364
+ },
365
+ then: {
366
+ kind: 'Finding',
367
+ message:
368
+ 'AST heuristic detected hardcoded sensitive Swift string; Keychain, secure config or environment-specific secrets remain the preferred baseline.',
369
+ code: 'HEURISTICS_IOS_SECURITY_HARDCODED_SENSITIVE_STRING_AST',
370
+ },
371
+ },
334
372
  {
335
373
  id: 'heuristics.ios.networking.alamofire.ast',
336
374
  description: 'Detects Alamofire usage in iOS production code; URLSession is the preferred baseline for new code.',
@@ -82,6 +82,10 @@ const registryByRuleId: Record<string, SkillsDetectorBinding> = {
82
82
  'ios.architecture.custom-singleton',
83
83
  ['heuristics.ios.architecture.custom-singleton.ast']
84
84
  ),
85
+ 'skills.ios.guideline.ios.swinject-prohibido-di-manual-o-environment': heuristicDetector(
86
+ 'ios.architecture.swinject',
87
+ ['heuristics.ios.architecture.swinject.ast']
88
+ ),
85
89
  'skills.ios.guideline.ios.magic-numbers-usar-constantes-con-nombres': heuristicDetector(
86
90
  'ios.maintainability.magic-number-layout',
87
91
  ['heuristics.ios.maintainability.magic-number-layout.ast']
@@ -94,6 +98,10 @@ const registryByRuleId: Record<string, SkillsDetectorBinding> = {
94
98
  'ios.logging.sensitive-data',
95
99
  ['heuristics.ios.logging.sensitive-data.ast']
96
100
  ),
101
+ 'skills.ios.guideline.ios.obfuscation-strings-sensibles-en-co-digo': heuristicDetector(
102
+ 'ios.security.hardcoded-sensitive-string',
103
+ ['heuristics.ios.security.hardcoded-sensitive-string.ast']
104
+ ),
97
105
  'skills.ios.guideline.ios.alamofire-prohibido-usar-urlsession-nativo': heuristicDetector(
98
106
  'ios.networking.alamofire',
99
107
  ['heuristics.ios.networking.alamofire.ast']
@@ -480,6 +480,17 @@ const normalizeKnownRuleTarget = (
480
480
  ) {
481
481
  return 'skills.ios.guideline.ios.magic-numbers-usar-constantes-con-nombres';
482
482
  }
483
+ if (includes('swinject')) {
484
+ return 'skills.ios.guideline.ios.swinject-prohibido-di-manual-o-environment';
485
+ }
486
+ if (
487
+ includes('obfuscation') ||
488
+ includes('strings sensibles en codigo') ||
489
+ includes('strings sensibles en co digo') ||
490
+ includes('sensitive strings')
491
+ ) {
492
+ return 'skills.ios.guideline.ios.obfuscation-strings-sensibles-en-co-digo';
493
+ }
483
494
  if (
484
495
  includes('mixing legacy xctest style') ||
485
496
  includes('mixed xctest and swift testing') ||
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pumuki",
3
- "version": "6.3.214",
3
+ "version": "6.3.216",
4
4
  "description": "Enterprise-grade AST Intelligence System with multi-platform support (iOS, Android, Backend, Frontend) and Feature-First + DDD + Clean Architecture enforcement. Includes dynamic violations API for intelligent querying.",
5
5
  "main": "index.js",
6
6
  "bin": {
package/skills.lock.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": "1.0",
3
3
  "compilerVersion": "1.0.0",
4
- "generatedAt": "2026-05-13T13:13:49.119Z",
4
+ "generatedAt": "2026-05-13T13:25:12.010Z",
5
5
  "bundles": [
6
6
  {
7
7
  "name": "android-guidelines",
@@ -5764,7 +5764,7 @@
5764
5764
  "name": "ios-guidelines",
5765
5765
  "version": "1.0.0",
5766
5766
  "source": "file:vendor/skills/ios-enterprise-rules/SKILL.md",
5767
- "hash": "45fa3aefa9324032a7a0ce988d5546db63b0d64936bf81c4dbaa4906e5f4a544",
5767
+ "hash": "c7b96d97cd02175dacf17b64cb8bdd1be7b5978dd2f74c7feb3bf3d462311467",
5768
5768
  "rules": [
5769
5769
  {
5770
5770
  "id": "skills.ios.guideline.ios.accessibility-identifiers-para-localizar-elementos",
@@ -7192,7 +7192,7 @@
7192
7192
  "sourcePath": "vendor/skills/ios-enterprise-rules/SKILL.md",
7193
7193
  "confidence": "MEDIUM",
7194
7194
  "locked": true,
7195
- "evaluationMode": "DECLARATIVE",
7195
+ "evaluationMode": "AUTO",
7196
7196
  "origin": "core"
7197
7197
  },
7198
7198
  {
@@ -7912,7 +7912,7 @@
7912
7912
  "sourcePath": "vendor/skills/ios-enterprise-rules/SKILL.md",
7913
7913
  "confidence": "HIGH",
7914
7914
  "locked": true,
7915
- "evaluationMode": "DECLARATIVE",
7915
+ "evaluationMode": "AUTO",
7916
7916
  "origin": "core"
7917
7917
  },
7918
7918
  {