hunter-mate 0.1.7 → 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (239) hide show
  1. package/dist/assets/extension/background/service-worker.js +808 -153
  2. package/dist/assets/extension/build-info.json +1 -0
  3. package/dist/assets/extension/content/index.js +23 -5
  4. package/dist/assets/extension/manifest.json +5 -4
  5. package/dist/assets/extension/offscreen/offscreen.html +8 -0
  6. package/dist/assets/extension/offscreen/offscreen.js +149 -0
  7. package/dist/assets/extension/package.json +8 -1
  8. package/dist/assets/extension/sidepanel/index.css +2 -0
  9. package/dist/assets/extension/sidepanel/index.html +7 -394
  10. package/dist/assets/extension/sidepanel/index.js +53 -923
  11. package/dist/assets/server/app.module.js +11 -1
  12. package/dist/assets/server/app.module.js.map +1 -1
  13. package/dist/assets/server/auth/auth.middleware.js +9 -1
  14. package/dist/assets/server/auth/auth.middleware.js.map +1 -1
  15. package/dist/assets/server/build-info.json +1 -1
  16. package/dist/assets/server/customer/customer.controller.d.ts +18 -0
  17. package/dist/assets/server/customer/customer.controller.js +81 -0
  18. package/dist/assets/server/customer/customer.controller.js.map +1 -0
  19. package/dist/assets/server/customer/customer.entity.d.ts +17 -0
  20. package/dist/assets/server/customer/customer.entity.js +82 -0
  21. package/dist/assets/server/customer/customer.entity.js.map +1 -0
  22. package/dist/assets/server/customer/customer.module.d.ts +2 -0
  23. package/dist/assets/server/customer/customer.module.js +28 -0
  24. package/dist/assets/server/customer/customer.module.js.map +1 -0
  25. package/dist/assets/server/customer/customer.service.d.ts +36 -0
  26. package/dist/assets/server/customer/customer.service.js +200 -0
  27. package/dist/assets/server/customer/customer.service.js.map +1 -0
  28. package/dist/assets/server/db/schema-validator.service.d.ts +2 -0
  29. package/dist/assets/server/db/schema-validator.service.js +32 -1
  30. package/dist/assets/server/db/schema-validator.service.js.map +1 -1
  31. package/dist/assets/server/db/sqlite.module.d.ts +1 -0
  32. package/dist/assets/server/db/sqlite.module.js +12 -2
  33. package/dist/assets/server/db/sqlite.module.js.map +1 -1
  34. package/dist/assets/server/devops/devops-sink-init.d.ts +1 -14
  35. package/dist/assets/server/devops/devops-sink-init.js +3 -8
  36. package/dist/assets/server/devops/devops-sink-init.js.map +1 -1
  37. package/dist/assets/server/extension/extension-control.controller.d.ts +17 -1
  38. package/dist/assets/server/extension/extension-control.controller.js +68 -12
  39. package/dist/assets/server/extension/extension-control.controller.js.map +1 -1
  40. package/dist/assets/server/extension/extension-control.service.d.ts +6 -1
  41. package/dist/assets/server/extension/extension-control.service.js +27 -1
  42. package/dist/assets/server/extension/extension-control.service.js.map +1 -1
  43. package/dist/assets/server/extension/extension.module.js +2 -1
  44. package/dist/assets/server/extension/extension.module.js.map +1 -1
  45. package/dist/assets/server/extraction/adapter.service.d.ts +3 -0
  46. package/dist/assets/server/extraction/adapter.service.js +127 -6
  47. package/dist/assets/server/extraction/adapter.service.js.map +1 -1
  48. package/dist/assets/server/extraction/anomaly-report.service.js +1 -1
  49. package/dist/assets/server/extraction/anomaly-report.service.js.map +1 -1
  50. package/dist/assets/server/extraction/entities/adapter-rule.entity.d.ts +2 -0
  51. package/dist/assets/server/extraction/entities/adapter-rule.entity.js +10 -0
  52. package/dist/assets/server/extraction/entities/adapter-rule.entity.js.map +1 -1
  53. package/dist/assets/server/extraction/extraction-entity.controller.d.ts +21 -3
  54. package/dist/assets/server/extraction/extraction-entity.controller.js +44 -9
  55. package/dist/assets/server/extraction/extraction-entity.controller.js.map +1 -1
  56. package/dist/assets/server/extraction/extraction.module.js +13 -3
  57. package/dist/assets/server/extraction/extraction.module.js.map +1 -1
  58. package/dist/assets/server/extraction/extraction.service.d.ts +4 -1
  59. package/dist/assets/server/extraction/extraction.service.js +71 -13
  60. package/dist/assets/server/extraction/extraction.service.js.map +1 -1
  61. package/dist/assets/server/extraction/harness-overlay.service.d.ts +41 -0
  62. package/dist/assets/server/extraction/harness-overlay.service.js +319 -0
  63. package/dist/assets/server/extraction/harness-overlay.service.js.map +1 -0
  64. package/dist/assets/server/extraction/liepin-extractor.d.ts +1 -0
  65. package/dist/assets/server/extraction/liepin-extractor.js +172 -0
  66. package/dist/assets/server/extraction/liepin-extractor.js.map +1 -0
  67. package/dist/assets/server/extraction/script-rule.js +14 -2
  68. package/dist/assets/server/extraction/script-rule.js.map +1 -1
  69. package/dist/assets/server/governance/action-audit.entity.d.ts +12 -0
  70. package/dist/assets/server/governance/action-audit.entity.js +66 -0
  71. package/dist/assets/server/governance/action-audit.entity.js.map +1 -0
  72. package/dist/assets/server/governance/governance.command-recorder.d.ts +17 -0
  73. package/dist/assets/server/governance/governance.command-recorder.js +98 -0
  74. package/dist/assets/server/governance/governance.command-recorder.js.map +1 -0
  75. package/dist/assets/server/governance/governance.controller.d.ts +14 -0
  76. package/dist/assets/server/governance/governance.controller.js +77 -0
  77. package/dist/assets/server/governance/governance.controller.js.map +1 -0
  78. package/dist/assets/server/governance/governance.ingester.d.ts +21 -0
  79. package/dist/assets/server/governance/governance.ingester.js +117 -0
  80. package/dist/assets/server/governance/governance.ingester.js.map +1 -0
  81. package/dist/assets/server/governance/governance.module.d.ts +2 -0
  82. package/dist/assets/server/governance/governance.module.js +27 -0
  83. package/dist/assets/server/governance/governance.module.js.map +1 -0
  84. package/dist/assets/server/governance/governance.service.d.ts +122 -0
  85. package/dist/assets/server/governance/governance.service.js +398 -0
  86. package/dist/assets/server/governance/governance.service.js.map +1 -0
  87. package/dist/assets/server/jobcase/jobcase.controller.d.ts +1 -0
  88. package/dist/assets/server/jobcase/jobcase.entity.d.ts +1 -0
  89. package/dist/assets/server/jobcase/jobcase.entity.js +6 -0
  90. package/dist/assets/server/jobcase/jobcase.entity.js.map +1 -1
  91. package/dist/assets/server/jobcase/jobcase.service.d.ts +2 -0
  92. package/dist/assets/server/jobcase/jobcase.service.js +2 -1
  93. package/dist/assets/server/jobcase/jobcase.service.js.map +1 -1
  94. package/dist/assets/server/main.js +1 -0
  95. package/dist/assets/server/main.js.map +1 -1
  96. package/dist/assets/server/package.json +1 -1
  97. package/dist/assets/server/preference/preference.controller.d.ts +14 -0
  98. package/dist/assets/server/preference/preference.controller.js +66 -0
  99. package/dist/assets/server/preference/preference.controller.js.map +1 -0
  100. package/dist/assets/server/preference/preference.entity.d.ts +13 -0
  101. package/dist/assets/server/preference/preference.entity.js +77 -0
  102. package/dist/assets/server/preference/preference.entity.js.map +1 -0
  103. package/dist/assets/server/preference/preference.module.d.ts +2 -0
  104. package/dist/assets/server/preference/preference.module.js +26 -0
  105. package/dist/assets/server/preference/preference.module.js.map +1 -0
  106. package/dist/assets/server/preference/preference.service.d.ts +33 -0
  107. package/dist/assets/server/preference/preference.service.js +122 -0
  108. package/dist/assets/server/preference/preference.service.js.map +1 -0
  109. package/dist/assets/server/recording/recording-event-queue.service.js +1 -1
  110. package/dist/assets/server/recording/recording-event-queue.service.js.map +1 -1
  111. package/dist/assets/server/recording/recording-retention.service.d.ts +19 -2
  112. package/dist/assets/server/recording/recording-retention.service.js +95 -6
  113. package/dist/assets/server/recording/recording-retention.service.js.map +1 -1
  114. package/dist/assets/server/recording/recording-snapshot.service.d.ts +1 -0
  115. package/dist/assets/server/recording/recording-snapshot.service.js +4 -0
  116. package/dist/assets/server/recording/recording-snapshot.service.js.map +1 -1
  117. package/dist/assets/server/recording/recording.controller.d.ts +10 -0
  118. package/dist/assets/server/recording/recording.controller.js +19 -0
  119. package/dist/assets/server/recording/recording.controller.js.map +1 -1
  120. package/dist/assets/server/recording/recording.gateway.js +15 -0
  121. package/dist/assets/server/recording/recording.gateway.js.map +1 -1
  122. package/dist/assets/server/recording/recording.module.js +6 -1
  123. package/dist/assets/server/recording/recording.module.js.map +1 -1
  124. package/dist/assets/server/recording/recording.service.d.ts +5 -0
  125. package/dist/assets/server/recording/recording.service.js +10 -0
  126. package/dist/assets/server/recording/recording.service.js.map +1 -1
  127. package/dist/assets/server/remark/remark.controller.d.ts +1 -1
  128. package/dist/assets/server/remark/remark.controller.js +1 -10
  129. package/dist/assets/server/remark/remark.controller.js.map +1 -1
  130. package/dist/assets/server/remark/remark.entity.d.ts +1 -1
  131. package/dist/assets/server/remark/remark.entity.js.map +1 -1
  132. package/dist/assets/server/site/entities/site-registry.entity.d.ts +1 -1
  133. package/dist/assets/server/site/entities/site-registry.entity.js +1 -1
  134. package/dist/assets/server/site/entities/site-registry.entity.js.map +1 -1
  135. package/dist/assets/server/site/site.controller.d.ts +1 -1
  136. package/dist/assets/server/site/site.service.d.ts +5 -1
  137. package/dist/assets/server/site/site.service.js +13 -0
  138. package/dist/assets/server/site/site.service.js.map +1 -1
  139. package/dist/assets/server/system/system.controller.d.ts +1 -0
  140. package/dist/assets/server/system/system.controller.js +1 -1
  141. package/dist/assets/server/system/system.controller.js.map +1 -1
  142. package/dist/assets/server/system/system.service.d.ts +1 -0
  143. package/dist/assets/server/system/system.service.js +3 -2
  144. package/dist/assets/server/system/system.service.js.map +1 -1
  145. package/dist/cache/db.js +6 -6
  146. package/dist/commands/addons.js +2 -1
  147. package/dist/commands/cache.js +1 -1
  148. package/dist/commands/case.d.ts +67 -0
  149. package/dist/commands/case.js +101 -0
  150. package/dist/commands/config.d.ts +4 -0
  151. package/dist/commands/config.js +8 -1
  152. package/dist/commands/customer.d.ts +25 -0
  153. package/dist/commands/customer.js +137 -0
  154. package/dist/commands/doctor.js +33 -9
  155. package/dist/commands/extension.js +21 -16
  156. package/dist/commands/extras.d.ts +18 -3
  157. package/dist/commands/extras.js +162 -5
  158. package/dist/commands/init.d.ts +1 -1
  159. package/dist/commands/init.js +3 -4
  160. package/dist/commands/install.d.ts +5 -0
  161. package/dist/commands/install.js +22 -42
  162. package/dist/commands/issue-env.d.ts +23 -0
  163. package/dist/commands/issue-env.js +101 -0
  164. package/dist/commands/job.d.ts +2 -1
  165. package/dist/commands/job.js +25 -5
  166. package/dist/commands/login.d.ts +4 -0
  167. package/dist/commands/login.js +57 -4
  168. package/dist/commands/migrate.d.ts +32 -0
  169. package/dist/commands/migrate.js +116 -0
  170. package/dist/commands/note.d.ts +3 -0
  171. package/dist/commands/note.js +75 -0
  172. package/dist/commands/ops.js +64 -13
  173. package/dist/commands/preference.d.ts +6 -0
  174. package/dist/commands/preference.js +80 -0
  175. package/dist/commands/record.js +1 -1
  176. package/dist/commands/report.js +1 -1
  177. package/dist/commands/search.js +1 -1
  178. package/dist/commands/server.d.ts +12 -0
  179. package/dist/commands/server.js +182 -18
  180. package/dist/commands/status.d.ts +4 -0
  181. package/dist/commands/status.js +16 -6
  182. package/dist/commands/update.js +7 -8
  183. package/dist/config.d.ts +21 -0
  184. package/dist/config.js +27 -0
  185. package/dist/extension-sync.d.ts +35 -0
  186. package/dist/extension-sync.js +159 -0
  187. package/dist/i18n/locales/en-US.json +17 -1
  188. package/dist/i18n/locales/zh-CN.json +17 -1
  189. package/dist/index.js +17 -0
  190. package/dist/keychain.d.ts +16 -1
  191. package/dist/keychain.js +43 -16
  192. package/dist/logger.js +2 -2
  193. package/dist/postinstall.d.ts +1 -0
  194. package/dist/postinstall.js +31 -0
  195. package/dist/updater.js +2 -2
  196. package/dist/utils/artifact-checksum.d.ts +4 -0
  197. package/dist/utils/artifact-checksum.js +40 -0
  198. package/dist/utils/command-error.d.ts +4 -2
  199. package/dist/utils/command-error.js +19 -3
  200. package/dist/utils/link.d.ts +18 -0
  201. package/dist/utils/link.js +83 -0
  202. package/dist/utils/local-http.d.ts +7 -0
  203. package/dist/utils/local-http.js +30 -0
  204. package/dist/version.js +86 -49
  205. package/dist/watchdog.d.ts +8 -0
  206. package/dist/watchdog.js +49 -9
  207. package/dist/web/dist/404.html +1 -1
  208. package/dist/web/dist/_next/static/chunks/app/logs/page-d478031d49f7ba00.js +1 -0
  209. package/dist/web/dist/_next/static/chunks/{main-app-80b038a312917d90.js → main-app-0af848156a5b13fc.js} +1 -1
  210. package/dist/web/dist/_next/static/chunks/pages/{_app-da7d628f49271ece.js → _app-3d844792ec91e4d1.js} +2 -2
  211. package/dist/web/dist/auth/verify.html +1 -1
  212. package/dist/web/dist/auth/verify.txt +1 -1
  213. package/dist/web/dist/companies.html +1 -1
  214. package/dist/web/dist/companies.txt +1 -1
  215. package/dist/web/dist/entity.html +1 -1
  216. package/dist/web/dist/entity.txt +1 -1
  217. package/dist/web/dist/index.html +1 -1
  218. package/dist/web/dist/index.txt +1 -1
  219. package/dist/web/dist/jobs.html +1 -1
  220. package/dist/web/dist/jobs.txt +1 -1
  221. package/dist/web/dist/logs.html +1 -1
  222. package/dist/web/dist/logs.txt +2 -2
  223. package/dist/web/dist/matching/jobs/placeholder/talents.html +1 -1
  224. package/dist/web/dist/matching/jobs/placeholder/talents.txt +1 -1
  225. package/dist/web/dist/matching/portraits/placeholder/jobs.html +1 -1
  226. package/dist/web/dist/matching/portraits/placeholder/jobs.txt +1 -1
  227. package/dist/web/dist/parselog.html +1 -1
  228. package/dist/web/dist/parselog.txt +1 -1
  229. package/dist/web/dist/recordings.html +1 -1
  230. package/dist/web/dist/recordings.txt +1 -1
  231. package/dist/web/dist/snapshots/placeholder/agent-prompt.html +1 -1
  232. package/dist/web/dist/snapshots/placeholder/agent-prompt.txt +1 -1
  233. package/dist/web/dist/talents.html +1 -1
  234. package/dist/web/dist/talents.txt +1 -1
  235. package/package.json +6 -4
  236. package/scripts/postinstall-run.mjs +14 -0
  237. package/dist/web/dist/_next/static/chunks/app/logs/page-9f41d44fa1add723.js +0 -1
  238. /package/dist/web/dist/_next/static/{hqJ-7vr4X71DNfzZugHJ- → 3bVkK4pAgbbmp5r0ThyBL}/_buildManifest.js +0 -0
  239. /package/dist/web/dist/_next/static/{hqJ-7vr4X71DNfzZugHJ- → 3bVkK4pAgbbmp5r0ThyBL}/_ssgManifest.js +0 -0
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ var GovernanceIngester_1;
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.GovernanceIngester = exports.DERIVABLE_ACTIONS = void 0;
17
+ const common_1 = require("@nestjs/common");
18
+ const typeorm_1 = require("@nestjs/typeorm");
19
+ const typeorm_2 = require("typeorm");
20
+ const recording_event_bus_service_1 = require("../recording/recording-event-bus.service");
21
+ const action_audit_entity_1 = require("./action-audit.entity");
22
+ const governance_service_1 = require("./governance.service");
23
+ exports.DERIVABLE_ACTIONS = new Set([
24
+ 'profile_view',
25
+ 'search_run',
26
+ 'invite',
27
+ 'note_invite',
28
+ 'page_scroll',
29
+ ]);
30
+ const MAX_SESSION_MEMORY = 5000;
31
+ let GovernanceIngester = GovernanceIngester_1 = class GovernanceIngester {
32
+ eventBus;
33
+ governanceService;
34
+ auditRepo;
35
+ logger = new common_1.Logger(GovernanceIngester_1.name);
36
+ lastUrlBySession = new Map();
37
+ constructor(eventBus, governanceService, auditRepo) {
38
+ this.eventBus = eventBus;
39
+ this.governanceService = governanceService;
40
+ this.auditRepo = auditRepo;
41
+ }
42
+ onModuleInit() {
43
+ this.eventBus.on('recording.events.persisted', (evt) => {
44
+ this.ingest(evt.entities).catch((err) => {
45
+ this.logger.warn(`governance ingest 失败: ${err?.message || err}`);
46
+ });
47
+ });
48
+ }
49
+ async ingest(events) {
50
+ let derived = 0;
51
+ for (const e of events) {
52
+ if (!e.sourceUrl)
53
+ continue;
54
+ const last = this.lastUrlBySession.get(e.sessionId);
55
+ if (last === e.sourceUrl)
56
+ continue;
57
+ this.setLastUrl(e.sessionId, e.sourceUrl);
58
+ let url;
59
+ try {
60
+ url = new URL(e.sourceUrl);
61
+ }
62
+ catch {
63
+ continue;
64
+ }
65
+ const host = url.hostname.toLowerCase();
66
+ const profile = this.governanceService.loadProfile(host);
67
+ if (!profile?.account_type)
68
+ continue;
69
+ const rules = this.governanceService.loadActionDerivation(host);
70
+ if (!rules)
71
+ continue;
72
+ const target = `${url.pathname}${url.search}`;
73
+ for (const rule of rules) {
74
+ if (!exports.DERIVABLE_ACTIONS.has(rule.action))
75
+ continue;
76
+ let re;
77
+ try {
78
+ re = new RegExp(rule.path_pattern);
79
+ }
80
+ catch {
81
+ this.logger.warn(`非法 path_pattern 跳过: ${rule.path_pattern}`);
82
+ continue;
83
+ }
84
+ if (!re.test(target))
85
+ continue;
86
+ if (await this.governanceService.recentAuditExists(profile.site, rule.action, e.sourceUrl)) {
87
+ continue;
88
+ }
89
+ await this.auditRepo.save(this.auditRepo.create({
90
+ site: profile.site,
91
+ accountType: profile.account_type,
92
+ actionType: rule.action,
93
+ sessionId: e.sessionId,
94
+ tabId: e.tabId != null ? String(e.tabId) : null,
95
+ detail: JSON.stringify({ derivedFrom: 'recording', url: e.sourceUrl }),
96
+ }));
97
+ derived++;
98
+ break;
99
+ }
100
+ }
101
+ return derived;
102
+ }
103
+ setLastUrl(sessionId, url) {
104
+ if (this.lastUrlBySession.size >= MAX_SESSION_MEMORY)
105
+ this.lastUrlBySession.clear();
106
+ this.lastUrlBySession.set(sessionId, url);
107
+ }
108
+ };
109
+ exports.GovernanceIngester = GovernanceIngester;
110
+ exports.GovernanceIngester = GovernanceIngester = GovernanceIngester_1 = __decorate([
111
+ (0, common_1.Injectable)(),
112
+ __param(2, (0, typeorm_1.InjectRepository)(action_audit_entity_1.ActionAudit)),
113
+ __metadata("design:paramtypes", [recording_event_bus_service_1.RecordingEventBus,
114
+ governance_service_1.GovernanceService,
115
+ typeorm_2.Repository])
116
+ ], GovernanceIngester);
117
+ //# sourceMappingURL=governance.ingester.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"governance.ingester.js","sourceRoot":"","sources":["../../src/governance/governance.ingester.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare class GovernanceModule {
2
+ }
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.GovernanceModule = void 0;
10
+ const common_1 = require("@nestjs/common");
11
+ const typeorm_1 = require("@nestjs/typeorm");
12
+ const action_audit_entity_1 = require("./action-audit.entity");
13
+ const governance_service_1 = require("./governance.service");
14
+ const governance_controller_1 = require("./governance.controller");
15
+ const governance_command_recorder_1 = require("./governance.command-recorder");
16
+ let GovernanceModule = class GovernanceModule {
17
+ };
18
+ exports.GovernanceModule = GovernanceModule;
19
+ exports.GovernanceModule = GovernanceModule = __decorate([
20
+ (0, common_1.Module)({
21
+ imports: [typeorm_1.TypeOrmModule.forFeature([action_audit_entity_1.ActionAudit])],
22
+ controllers: [governance_controller_1.GovernanceController],
23
+ providers: [governance_service_1.GovernanceService, governance_command_recorder_1.GovernanceCommandRecorder],
24
+ exports: [governance_service_1.GovernanceService, governance_command_recorder_1.GovernanceCommandRecorder],
25
+ })
26
+ ], GovernanceModule);
27
+ //# sourceMappingURL=governance.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"governance.module.js","sourceRoot":"","sources":["../../src/governance/governance.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,6CAAgD;AAChD,+DAAoD;AACpD,6DAAyD;AACzD,mEAA+D;AAC/D,+EAA0E;AAQnE,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;CAAG,CAAA;AAAnB,4CAAgB;2BAAhB,gBAAgB;IAN5B,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,uBAAa,CAAC,UAAU,CAAC,CAAC,iCAAW,CAAC,CAAC,CAAC;QAClD,WAAW,EAAE,CAAC,4CAAoB,CAAC;QACnC,SAAS,EAAE,CAAC,sCAAiB,EAAE,uDAAyB,CAAC;QACzD,OAAO,EAAE,CAAC,sCAAiB,EAAE,uDAAyB,CAAC;KACxD,CAAC;GACW,gBAAgB,CAAG"}
@@ -0,0 +1,122 @@
1
+ import { Repository } from 'typeorm';
2
+ import { ActionAudit, GovernanceActionType } from './action-audit.entity';
3
+ export interface RiskQuotaLimit {
4
+ per_hour?: number;
5
+ per_day?: number;
6
+ per_week?: number;
7
+ per_month?: number;
8
+ source?: string;
9
+ confidence?: string;
10
+ }
11
+ export interface RiskSchedule {
12
+ work_hours_local: [number, number];
13
+ off_hours_multiplier: number;
14
+ marathon_session_min: number;
15
+ advisory_escalation: number;
16
+ }
17
+ export interface RiskPacing {
18
+ min_action_gap_ms: [number, number];
19
+ scroll_per_screen_ms: [number, number];
20
+ page_turn_gap_ms: [number, number];
21
+ }
22
+ export interface RiskHardRules {
23
+ forbid_api_interception: boolean;
24
+ forbid_cdp_navigation: boolean;
25
+ forbid_headless: boolean;
26
+ captcha_manual_only: boolean;
27
+ }
28
+ export interface RiskStopCode {
29
+ code: string;
30
+ dom_signals?: string[];
31
+ response_signals?: string[];
32
+ action?: string;
33
+ }
34
+ export interface RiskProfile {
35
+ site: string;
36
+ version?: string;
37
+ account_type?: string;
38
+ account_quotas: Record<string, Record<string, RiskQuotaLimit>>;
39
+ schedule: RiskSchedule;
40
+ pacing: RiskPacing;
41
+ hard_rules: RiskHardRules;
42
+ stop_codes?: RiskStopCode[];
43
+ }
44
+ export interface ActionDerivationRule {
45
+ action: string;
46
+ path_pattern: string;
47
+ }
48
+ export interface RecordActionDto {
49
+ site: string;
50
+ accountType: string;
51
+ actionType: GovernanceActionType;
52
+ sessionId: string;
53
+ tabId?: string | null;
54
+ detail?: unknown;
55
+ stopCode?: string | null;
56
+ }
57
+ export interface UsageWindow {
58
+ window: 'hour' | 'day' | 'week' | 'month';
59
+ used: number;
60
+ limit: number | null;
61
+ }
62
+ export interface GovernanceAdvisory {
63
+ offHours: boolean;
64
+ marathonMinutes: number;
65
+ gapMs: number;
66
+ }
67
+ export interface GovernanceCheckResult {
68
+ allowed: boolean;
69
+ reason?: string;
70
+ nextAllowedAt?: string;
71
+ usage: UsageWindow[];
72
+ advisory?: GovernanceAdvisory;
73
+ }
74
+ export interface GovernanceStatusResult {
75
+ available: boolean;
76
+ reason?: string;
77
+ reasonCode?: ProfileUnavailableCode;
78
+ reasonDetail?: string;
79
+ site: string;
80
+ accountType: string;
81
+ actions: Array<{
82
+ actionType: string;
83
+ usage: UsageWindow[];
84
+ basis?: {
85
+ source?: string;
86
+ confidence?: string;
87
+ };
88
+ }>;
89
+ advisory: GovernanceAdvisory;
90
+ }
91
+ export declare const RISK_PROFILE_UNAVAILABLE = "risk_profile_unavailable";
92
+ export type ProfileUnavailableCode = 'harness_path_missing' | 'risk_profile_missing' | 'risk_profile_invalid';
93
+ export declare class GovernanceService {
94
+ private readonly auditRepo;
95
+ private readonly logger;
96
+ private readonly profileCache;
97
+ private readonly derivationCache;
98
+ constructor(auditRepo: Repository<ActionAudit>);
99
+ record(dto: RecordActionDto): Promise<ActionAudit>;
100
+ check(site: string, accountType: string, actionType: GovernanceActionType, harnessPath?: string): Promise<GovernanceCheckResult>;
101
+ status(site: string, accountType: string, harnessPath?: string): Promise<GovernanceStatusResult>;
102
+ private windowUsage;
103
+ private countSince;
104
+ private buildAdvisory;
105
+ private marathonMinutesSince;
106
+ sampleGap(profile: RiskProfile, offHours: boolean, marathonMinutes?: number): number;
107
+ resolveHarnessPath(harnessPath?: string): string | null;
108
+ loadProfile(site: string, harnessPath?: string): RiskProfile | null;
109
+ loadActionDerivation(site: string, harnessPath?: string): ActionDerivationRule[] | null;
110
+ profileUnavailable(site: string, harnessPath?: string): {
111
+ code: ProfileUnavailableCode;
112
+ detail?: string;
113
+ } | null;
114
+ recentAuditExists(site: string, actionType: GovernanceActionType, url: string, windowMs?: number): Promise<boolean>;
115
+ private resolveRiskProfileRef;
116
+ clearProfileCache(): void;
117
+ }
118
+ export declare function assertHardRules(profile: RiskProfile, site: string): void;
119
+ export declare function startOfHour(d: Date): Date;
120
+ export declare function startOfDay(d: Date): Date;
121
+ export declare function startOfWeek(d: Date): Date;
122
+ export declare function startOfMonth(d: Date): Date;
@@ -0,0 +1,398 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ var GovernanceService_1;
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.GovernanceService = exports.RISK_PROFILE_UNAVAILABLE = void 0;
17
+ exports.assertHardRules = assertHardRules;
18
+ exports.startOfHour = startOfHour;
19
+ exports.startOfDay = startOfDay;
20
+ exports.startOfWeek = startOfWeek;
21
+ exports.startOfMonth = startOfMonth;
22
+ const common_1 = require("@nestjs/common");
23
+ const typeorm_1 = require("@nestjs/typeorm");
24
+ const typeorm_2 = require("typeorm");
25
+ const fs = require("fs");
26
+ const path = require("path");
27
+ const action_audit_entity_1 = require("./action-audit.entity");
28
+ const harness_overlay_service_1 = require("../extraction/harness-overlay.service");
29
+ const ALL_WINDOWS = ['hour', 'day', 'week', 'month'];
30
+ const HARD_RULE_KEYS = [
31
+ 'forbid_api_interception',
32
+ 'forbid_cdp_navigation',
33
+ 'forbid_headless',
34
+ 'captcha_manual_only',
35
+ ];
36
+ exports.RISK_PROFILE_UNAVAILABLE = 'risk_profile_unavailable';
37
+ let GovernanceService = GovernanceService_1 = class GovernanceService {
38
+ auditRepo;
39
+ logger = new common_1.Logger(GovernanceService_1.name);
40
+ profileCache = new Map();
41
+ derivationCache = new Map();
42
+ constructor(auditRepo) {
43
+ this.auditRepo = auditRepo;
44
+ }
45
+ async record(dto) {
46
+ const entity = this.auditRepo.create({
47
+ site: dto.site,
48
+ accountType: dto.accountType,
49
+ actionType: dto.actionType,
50
+ sessionId: dto.sessionId,
51
+ tabId: dto.tabId ?? null,
52
+ detail: dto.detail === undefined ? null : JSON.stringify(dto.detail),
53
+ stopCode: dto.stopCode ?? null,
54
+ });
55
+ return this.auditRepo.save(entity);
56
+ }
57
+ async check(site, accountType, actionType, harnessPath) {
58
+ const profile = this.loadProfile(site, harnessPath);
59
+ if (!profile) {
60
+ return { allowed: false, reason: exports.RISK_PROFILE_UNAVAILABLE, usage: [] };
61
+ }
62
+ assertHardRules(profile, site);
63
+ const quotas = profile.account_quotas?.[accountType]?.[actionType];
64
+ const usage = await this.windowUsage(site, accountType, actionType, profile, quotas);
65
+ const exceeded = usage.filter((u) => u.limit != null && u.used > u.limit);
66
+ if (exceeded.length > 0) {
67
+ const now = new Date();
68
+ const next = exceeded
69
+ .map((u) => windowEnd(u.window, now))
70
+ .reduce((a, b) => (a > b ? a : b));
71
+ const worst = exceeded.reduce((a, b) => ((a.limit ?? 0) - a.used <= (b.limit ?? 0) - b.used ? a : b));
72
+ return {
73
+ allowed: false,
74
+ reason: `quota_exceeded:${worst.window}`,
75
+ nextAllowedAt: next.toISOString(),
76
+ usage,
77
+ advisory: await this.buildAdvisory(profile, site, accountType),
78
+ };
79
+ }
80
+ return { allowed: true, usage, advisory: await this.buildAdvisory(profile, site, accountType) };
81
+ }
82
+ async status(site, accountType, harnessPath) {
83
+ const profile = this.loadProfile(site, harnessPath);
84
+ const advisory = profile
85
+ ? await this.buildAdvisory(profile, site, accountType)
86
+ : emptyAdvisory();
87
+ if (!profile) {
88
+ const un = this.profileUnavailable(site, harnessPath);
89
+ return {
90
+ available: false,
91
+ reason: exports.RISK_PROFILE_UNAVAILABLE,
92
+ reasonCode: un?.code,
93
+ reasonDetail: un?.detail,
94
+ site,
95
+ accountType,
96
+ actions: [],
97
+ advisory,
98
+ };
99
+ }
100
+ const tierQuotas = profile.account_quotas?.[accountType] ?? {};
101
+ const actions = [];
102
+ for (const actionType of Object.keys(tierQuotas)) {
103
+ const usage = await this.windowUsage(site, accountType, actionType, profile, tierQuotas[actionType]);
104
+ actions.push({
105
+ actionType,
106
+ usage,
107
+ basis: {
108
+ source: tierQuotas[actionType]?.source,
109
+ confidence: tierQuotas[actionType]?.confidence,
110
+ },
111
+ });
112
+ }
113
+ return { available: true, site, accountType, actions, advisory };
114
+ }
115
+ async windowUsage(site, accountType, actionType, _profile, quota) {
116
+ const now = new Date();
117
+ const limits = {
118
+ hour: quota?.per_hour ?? null,
119
+ day: quota?.per_day ?? null,
120
+ week: quota?.per_week ?? null,
121
+ month: quota?.per_month ?? null,
122
+ };
123
+ const starts = {
124
+ hour: startOfHour(now),
125
+ day: startOfDay(now),
126
+ week: startOfWeek(now),
127
+ month: startOfMonth(now),
128
+ };
129
+ const usage = [];
130
+ for (const w of ALL_WINDOWS) {
131
+ const used = await this.countSince(site, accountType, actionType, starts[w]);
132
+ usage.push({ window: w, used, limit: limits[w] });
133
+ }
134
+ return usage;
135
+ }
136
+ countSince(site, accountType, actionType, since) {
137
+ return this.auditRepo.count({
138
+ where: {
139
+ site,
140
+ accountType,
141
+ actionType: actionType,
142
+ createdAt: (0, typeorm_2.Between)(since, new Date(864000000000000)),
143
+ },
144
+ });
145
+ }
146
+ async buildAdvisory(profile, site, accountType) {
147
+ const now = new Date();
148
+ const [workStart, workEnd] = profile.schedule?.work_hours_local ?? [0, 24];
149
+ const hour = now.getHours();
150
+ const offHours = hour < workStart || hour >= workEnd;
151
+ const marathonMinutes = await this.marathonMinutesSince(site, accountType, startOfDay(now), now);
152
+ const gapMs = this.sampleGap(profile, offHours, marathonMinutes);
153
+ return { offHours, marathonMinutes, gapMs };
154
+ }
155
+ async marathonMinutesSince(site, accountType, since, now) {
156
+ const first = await this.auditRepo
157
+ .createQueryBuilder('a')
158
+ .select('MIN(a.createdAt)', 'first')
159
+ .where('a.site = :site', { site })
160
+ .andWhere('a.accountType = :accountType', { accountType })
161
+ .andWhere('a.createdAt >= :since', { since })
162
+ .getRawOne();
163
+ if (!first?.first)
164
+ return 0;
165
+ const ms = now.getTime() - new Date(first.first).getTime();
166
+ return Math.max(0, Math.floor(ms / 60000));
167
+ }
168
+ sampleGap(profile, offHours, marathonMinutes = 0) {
169
+ const [min, max] = profile.pacing?.min_action_gap_ms ?? [0, 0];
170
+ let gap = min + Math.random() * Math.max(0, max - min);
171
+ if (offHours)
172
+ gap *= profile.schedule?.off_hours_multiplier ?? 1;
173
+ if (marathonMinutes >= (profile.schedule?.marathon_session_min ?? Number.POSITIVE_INFINITY)) {
174
+ gap *= 2;
175
+ }
176
+ return Math.round(gap);
177
+ }
178
+ resolveHarnessPath(harnessPath) {
179
+ const p = (harnessPath ?? process.env.HUNTER_MATE_HARNESS_PATH ?? '').trim();
180
+ if (p)
181
+ return path.resolve(p);
182
+ try {
183
+ const home = process.env.HUNTER_MATE_HOME || process.env.HOME || process.env.USERPROFILE || '.';
184
+ const cfgFile = path.join(home, '.hunter-mate', 'config.json');
185
+ if (fs.existsSync(cfgFile)) {
186
+ const cfg = JSON.parse(fs.readFileSync(cfgFile, 'utf-8'));
187
+ const fromCfg = String(cfg?.harnessPath ?? '').trim();
188
+ if (fromCfg)
189
+ return path.resolve(fromCfg);
190
+ }
191
+ }
192
+ catch {
193
+ }
194
+ return null;
195
+ }
196
+ loadProfile(site, harnessPath) {
197
+ const root = this.resolveHarnessPath(harnessPath);
198
+ if (!root)
199
+ return null;
200
+ const cacheKey = `${root}|${site}`;
201
+ const cached = this.profileCache.get(cacheKey);
202
+ if (cached)
203
+ return cached;
204
+ try {
205
+ const riskProfileRef = this.resolveRiskProfileRef(site, root);
206
+ if (!riskProfileRef)
207
+ return null;
208
+ const profileFile = path.join(root, 'adapters', riskProfileRef);
209
+ if (!fs.existsSync(profileFile))
210
+ return null;
211
+ const doc = (0, harness_overlay_service_1.parseYamlSubset)(fs.readFileSync(profileFile, 'utf-8'), riskProfileRef);
212
+ if (!doc || typeof doc !== 'object' || !doc.account_quotas || !doc.schedule || !doc.pacing || !doc.hard_rules) {
213
+ this.logger.warn(`risk profile 结构不完整(缺 account_quotas/schedule/pacing/hard_rules): ${profileFile}`);
214
+ return null;
215
+ }
216
+ const profile = normalizeProfile(doc);
217
+ this.profileCache.set(cacheKey, profile);
218
+ return profile;
219
+ }
220
+ catch (e) {
221
+ this.logger.warn(`risk profile 加载失败(site=${site}): ${e?.message || e}`);
222
+ return null;
223
+ }
224
+ }
225
+ loadActionDerivation(site, harnessPath) {
226
+ const root = this.resolveHarnessPath(harnessPath);
227
+ if (!root)
228
+ return null;
229
+ const cacheKey = `${root}|${site}`;
230
+ if (this.derivationCache.has(cacheKey))
231
+ return this.derivationCache.get(cacheKey) ?? null;
232
+ let result = null;
233
+ try {
234
+ const riskProfileRef = this.resolveRiskProfileRef(site, root);
235
+ if (riskProfileRef) {
236
+ const derivationFile = path.join(root, 'adapters', path.dirname(riskProfileRef), 'action-derivation.yaml');
237
+ if (fs.existsSync(derivationFile)) {
238
+ const doc = (0, harness_overlay_service_1.parseYamlSubset)(fs.readFileSync(derivationFile, 'utf-8'), 'action-derivation.yaml');
239
+ const rules = Array.isArray(doc?.url_actions) ? doc.url_actions : [];
240
+ const valid = rules
241
+ .filter((r) => r && typeof r.action === 'string' && typeof r.path_pattern === 'string')
242
+ .map((r) => ({ action: r.action, path_pattern: r.path_pattern }));
243
+ if (valid.length > 0)
244
+ result = valid;
245
+ }
246
+ }
247
+ }
248
+ catch (e) {
249
+ this.logger.warn(`action derivation 加载失败(site=${site}): ${e?.message || e}`);
250
+ }
251
+ this.derivationCache.set(cacheKey, result);
252
+ return result;
253
+ }
254
+ profileUnavailable(site, harnessPath) {
255
+ const root = this.resolveHarnessPath(harnessPath);
256
+ if (!root)
257
+ return { code: 'harness_path_missing' };
258
+ let ref = null;
259
+ try {
260
+ ref = this.resolveRiskProfileRef(site, root);
261
+ }
262
+ catch {
263
+ return { code: 'risk_profile_missing' };
264
+ }
265
+ if (!ref)
266
+ return { code: 'risk_profile_missing' };
267
+ const profileFile = path.join(root, 'adapters', ref);
268
+ if (!fs.existsSync(profileFile))
269
+ return { code: 'risk_profile_missing', detail: profileFile };
270
+ try {
271
+ const doc = (0, harness_overlay_service_1.parseYamlSubset)(fs.readFileSync(profileFile, 'utf-8'), ref);
272
+ if (!doc || typeof doc !== 'object' || !doc.account_quotas || !doc.schedule || !doc.pacing || !doc.hard_rules) {
273
+ return { code: 'risk_profile_invalid', detail: profileFile };
274
+ }
275
+ }
276
+ catch (e) {
277
+ return { code: 'risk_profile_invalid', detail: `${profileFile}: ${e?.message || e}` };
278
+ }
279
+ return null;
280
+ }
281
+ async recentAuditExists(site, actionType, url, windowMs = 60 * 60 * 1000) {
282
+ const since = new Date(Date.now() - windowMs);
283
+ const escaped = url.replace(/[%_\\]/g, (m) => `\\${m}`);
284
+ const row = await this.auditRepo
285
+ .createQueryBuilder('a')
286
+ .where('a.site = :site', { site })
287
+ .andWhere('a.actionType = :actionType', { actionType })
288
+ .andWhere('a.createdAt >= :since', { since })
289
+ .andWhere("a.detail LIKE :pat ESCAPE '\\'", { pat: `%${escaped}%` })
290
+ .getOne();
291
+ return !!row;
292
+ }
293
+ resolveRiskProfileRef(site, root) {
294
+ const adaptersDir = path.join(root, 'adapters');
295
+ const indexFile = path.join(adaptersDir, 'index.yaml');
296
+ if (!fs.existsSync(indexFile))
297
+ return null;
298
+ const index = (0, harness_overlay_service_1.parseYamlSubset)(fs.readFileSync(indexFile, 'utf-8'), 'index.yaml');
299
+ const triggers = Array.isArray(index?.triggers) ? index.triggers : [];
300
+ for (const t of triggers) {
301
+ if (!t?.hostPattern || !t?.riskProfile)
302
+ continue;
303
+ try {
304
+ if (new RegExp(t.hostPattern).test(site)) {
305
+ return String(t.riskProfile);
306
+ }
307
+ }
308
+ catch {
309
+ }
310
+ }
311
+ return null;
312
+ }
313
+ clearProfileCache() {
314
+ this.profileCache.clear();
315
+ this.derivationCache.clear();
316
+ }
317
+ };
318
+ exports.GovernanceService = GovernanceService;
319
+ exports.GovernanceService = GovernanceService = GovernanceService_1 = __decorate([
320
+ (0, common_1.Injectable)(),
321
+ __param(0, (0, typeorm_1.InjectRepository)(action_audit_entity_1.ActionAudit)),
322
+ __metadata("design:paramtypes", [typeorm_2.Repository])
323
+ ], GovernanceService);
324
+ function emptyAdvisory() {
325
+ return { offHours: false, marathonMinutes: 0, gapMs: 0 };
326
+ }
327
+ function assertHardRules(profile, site) {
328
+ const rules = profile.hard_rules;
329
+ const violated = HARD_RULE_KEYS.filter((k) => rules?.[k] !== true);
330
+ if (violated.length > 0) {
331
+ throw new Error(`risk_profile_hard_rules_violated(site=${site}): ${violated.join(',')} 必须为 true — 画像不可用,禁止执行动作`);
332
+ }
333
+ }
334
+ function coercePair(value, fallback) {
335
+ if (Array.isArray(value) && value.length >= 2) {
336
+ return [Number(value[0]), Number(value[1])];
337
+ }
338
+ if (typeof value === 'string') {
339
+ const m = value.match(/^\[\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*\]$/);
340
+ if (m)
341
+ return [Number(m[1]), Number(m[2])];
342
+ }
343
+ return fallback;
344
+ }
345
+ function normalizeProfile(raw) {
346
+ const schedule = raw.schedule ?? {};
347
+ const pacing = raw.pacing ?? {};
348
+ return {
349
+ ...raw,
350
+ schedule: {
351
+ ...schedule,
352
+ work_hours_local: coercePair(schedule.work_hours_local, [0, 24]),
353
+ off_hours_multiplier: Number(schedule.off_hours_multiplier ?? 1),
354
+ marathon_session_min: Number(schedule.marathon_session_min ?? 45),
355
+ advisory_escalation: Number(schedule.advisory_escalation ?? 3),
356
+ },
357
+ pacing: {
358
+ ...pacing,
359
+ min_action_gap_ms: coercePair(pacing.min_action_gap_ms, [0, 0]),
360
+ scroll_per_screen_ms: coercePair(pacing.scroll_per_screen_ms, [0, 0]),
361
+ page_turn_gap_ms: coercePair(pacing.page_turn_gap_ms, [0, 0]),
362
+ },
363
+ };
364
+ }
365
+ function startOfHour(d) {
366
+ return new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), 0, 0, 0);
367
+ }
368
+ function startOfDay(d) {
369
+ return new Date(d.getFullYear(), d.getMonth(), d.getDate(), 0, 0, 0, 0);
370
+ }
371
+ function startOfWeek(d) {
372
+ const day = (d.getDay() + 6) % 7;
373
+ const s = startOfDay(d);
374
+ s.setDate(s.getDate() - day);
375
+ return s;
376
+ }
377
+ function startOfMonth(d) {
378
+ return new Date(d.getFullYear(), d.getMonth(), 1, 0, 0, 0, 0);
379
+ }
380
+ function windowEnd(w, now) {
381
+ const s = {
382
+ hour: startOfHour(now),
383
+ day: startOfDay(now),
384
+ week: startOfWeek(now),
385
+ month: startOfMonth(now),
386
+ }[w];
387
+ const end = new Date(s);
388
+ if (w === 'hour')
389
+ end.setHours(end.getHours() + 1);
390
+ else if (w === 'day')
391
+ end.setDate(end.getDate() + 1);
392
+ else if (w === 'week')
393
+ end.setDate(end.getDate() + 7);
394
+ else
395
+ end.setMonth(end.getMonth() + 1);
396
+ return end;
397
+ }
398
+ //# sourceMappingURL=governance.service.js.map