@nodatachat/guard 2.0.0 → 2.2.0

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.
package/LICENSE.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # NoData Guard License
2
2
 
3
- Copyright (c) 2026 NoDataChat Ltd. All rights reserved.
3
+ Copyright (c) 2026 Capsule Ltd. All rights reserved.
4
4
 
5
5
  ## Terms
6
6
 
7
- This software is proprietary. You may use it under the terms of your NoDataChat subscription agreement.
7
+ This software is proprietary. You may use it under the terms of your Capsule subscription agreement.
8
8
 
9
9
  ### Permitted Uses
10
10
  - Running scans on your own projects with a valid license key
@@ -19,10 +19,10 @@ This software is proprietary. You may use it under the terms of your NoDataChat
19
19
 
20
20
  ### Data Privacy
21
21
  - Guard runs locally on your machine
22
- - Source code is never uploaded to NoDataChat servers
22
+ - Source code is never uploaded to Capsule servers
23
23
  - Only metadata reports (table names, counts, scores) are transmitted
24
24
  - You can opt out of metadata transmission with --skip-send
25
25
 
26
- For the full license agreement, visit: https://nodatachat.com/legal/guard-license
26
+ For the full license agreement, visit: https://nodatacapsule.com/legal/guard-license
27
27
 
28
- Contact: legal@nodatachat.com
28
+ Contact: legal@nodatacapsule.com
package/README.md CHANGED
@@ -79,7 +79,7 @@ npx nodata-guard --license-key $NDC_LICENSE --ci --fail-on critical
79
79
 
80
80
  ## Dashboard
81
81
 
82
- After running Guard, log in at [nodatachat.com/guard](https://nodatachat.com/guard) with your license key to see:
82
+ After running Guard, log in at [nodatacapsule.com/guard](https://nodatacapsule.com/guard) with your license key to see:
83
83
 
84
84
  - Score trends over time
85
85
  - Scan history with comparison
@@ -114,7 +114,7 @@ Proprietary — see [LICENSE.md](LICENSE.md)
114
114
 
115
115
  ## Links
116
116
 
117
- - [Website](https://nodatachat.com)
118
- - [Guard Dashboard](https://nodatachat.com/guard)
119
- - [Getting Started](https://nodatachat.com/guard/onboarding)
120
- - [Pricing](https://nodatachat.com/pricing)
117
+ - [Website](https://nodatacapsule.com)
118
+ - [Guard Dashboard](https://nodatacapsule.com/guard)
119
+ - [Getting Started](https://nodatacapsule.com/guard/onboarding)
120
+ - [Pricing](https://nodatacapsule.com/pricing)
@@ -18,7 +18,7 @@ const crypto_1 = require("crypto");
18
18
  const fs_1 = require("fs");
19
19
  const path_1 = require("path");
20
20
  const GUARD_VERSION = "2.0.0";
21
- const API_BASE = process.env.GUARD_API_BASE || "https://nodatachat.com/api/guard";
21
+ const API_BASE = process.env.GUARD_API_BASE || "https://nodatacapsule.com/api/guard";
22
22
  // Dev license keys that work without server (for development and demos)
23
23
  const DEV_LICENSES = new Set(["NDC-DEV", "NDC-DEMO", "NDC-TEST"]);
24
24
  // ── Project fingerprint (directory structure only, no file contents) ──
package/dist/cli.js CHANGED
@@ -22,7 +22,6 @@ const activation_1 = require("./activation");
22
22
  const code_scanner_1 = require("./code-scanner");
23
23
  const db_scanner_1 = require("./db-scanner");
24
24
  const reporter_1 = require("./reporter");
25
- const registry_1 = require("./fixers/registry");
26
25
  const scheduler_1 = require("./fixers/scheduler");
27
26
  const VERSION = "2.0.0";
28
27
  async function main() {
@@ -35,10 +34,8 @@ async function main() {
35
34
  let failOn = null;
36
35
  let outputDir = process.cwd();
37
36
  let skipSend = false;
38
- let fixMode = "none";
39
37
  let schedulePreset;
40
38
  let ciProvider;
41
- let onlyFixers;
42
39
  for (let i = 0; i < args.length; i++) {
43
40
  switch (args[i]) {
44
41
  case "--license-key":
@@ -63,13 +60,14 @@ async function main() {
63
60
  skipSend = true;
64
61
  break;
65
62
  case "--fix-plan":
66
- fixMode = "plan";
63
+ console.log("\n ⚠ --fix-plan is deprecated. Capsule provides recommendations only.\n Run without this flag to see recommendations.\n");
67
64
  break;
68
65
  case "--fix":
69
- fixMode = "apply";
66
+ console.log("\n ⚠ --fix is deprecated. Capsule does not modify your code.\n Recommendations are provided in the scan output.\n");
70
67
  break;
71
68
  case "--fix-only":
72
- onlyFixers = args[++i]?.split(",");
69
+ i++;
70
+ console.log("\n ⚠ --fix-only is deprecated. Capsule provides recommendations only.\n");
73
71
  break;
74
72
  case "--schedule":
75
73
  schedulePreset = args[++i] || "weekly";
@@ -87,12 +85,44 @@ async function main() {
87
85
  }
88
86
  // Env fallbacks
89
87
  if (!licenseKey)
90
- licenseKey = process.env.NDC_LICENSE || process.env.NODATA_LICENSE_KEY;
88
+ licenseKey = process.env.NDC_LICENSE || process.env.NODATA_LICENSE_KEY || process.env.NODATA_API_KEY || process.env.NDC_API_KEY;
91
89
  if (!dbUrl)
92
90
  dbUrl = process.env.DATABASE_URL;
91
+ // Shared Protect config fallback (~/.nodata/config.json)
93
92
  if (!licenseKey) {
94
- console.error("\n Error: --license-key required (or set NDC_LICENSE env var)\n");
95
- printHelp();
93
+ try {
94
+ const home = process.env.HOME || process.env.USERPROFILE || "";
95
+ const configPath = require("path").join(home, ".nodata", "config.json");
96
+ if (require("fs").existsSync(configPath)) {
97
+ const config = JSON.parse(require("fs").readFileSync(configPath, "utf-8"));
98
+ if (config.api_key) {
99
+ licenseKey = config.api_key;
100
+ console.log(`\n \x1b[32m✓\x1b[0m Using API key from NoData Protect (~/.nodata/config.json)\n`);
101
+ }
102
+ }
103
+ }
104
+ catch { /* ignore */ }
105
+ }
106
+ // Capsule config fallback (.capsule.json)
107
+ if (!licenseKey) {
108
+ try {
109
+ const capsulePath = require("path").join(projectDir, ".capsule.json");
110
+ if (require("fs").existsSync(capsulePath)) {
111
+ const config = JSON.parse(require("fs").readFileSync(capsulePath, "utf-8"));
112
+ if (config.licenseKey) {
113
+ licenseKey = config.licenseKey;
114
+ console.log(`\n \x1b[32m✓\x1b[0m Using API key from Capsule config (.capsule.json)\n`);
115
+ }
116
+ }
117
+ }
118
+ catch { /* ignore */ }
119
+ }
120
+ if (!licenseKey) {
121
+ console.error("\n \x1b[31m✗\x1b[0m No API key found.\n");
122
+ console.error(" Options:");
123
+ console.error(" 1. Run \x1b[36mnpx @nodatachat/protect init\x1b[0m first (creates key automatically)");
124
+ console.error(" 2. Pass \x1b[36m--license-key YOUR_KEY\x1b[0m");
125
+ console.error(" 3. Set \x1b[36mNDC_LICENSE=YOUR_KEY\x1b[0m in environment\n");
96
126
  process.exit(1);
97
127
  }
98
128
  // ── Schedule setup (no scan needed) ──
@@ -204,12 +234,13 @@ async function main() {
204
234
  if (!skipSend) {
205
235
  log(ciMode, "Sending metadata to NoData...");
206
236
  try {
207
- const res = await fetch("https://nodatachat.com/api/guard/report", {
237
+ const res = await fetch("https://nodatacapsule.com/api/guard/report", {
208
238
  method: "POST",
209
239
  headers: {
210
240
  "Content-Type": "application/json",
211
241
  "X-Scan-Id": activation.scan_id,
212
242
  "X-Activation-Key": activation.activation_key,
243
+ "X-License-Key": licenseKey || "",
213
244
  },
214
245
  body: JSON.stringify(metadata),
215
246
  signal: AbortSignal.timeout(10000),
@@ -250,102 +281,48 @@ async function main() {
250
281
  console.log(" Your data never left your machine.");
251
282
  console.log(" Diff the two files to verify.\n");
252
283
  }
253
- // ── Step 8: Capsule — Fix Plan / Apply ──
254
- if (fixMode !== "none") {
255
- const config = loadOrCreateConfig(projectDir, { dbUrl, failOn });
256
- const fixerContext = {
257
- projectDir,
258
- dbUrl,
259
- config,
260
- scanResults: {
261
- piiFields: piiFields.map(f => ({
262
- table: f.table, column: f.column, pii_type: f.pii_type,
263
- encrypted: f.encrypted, encryption_pattern: f.encryption_pattern,
264
- })),
265
- routes: routes.map(r => ({ path: r.path, has_auth: r.has_auth, auth_type: r.auth_type })),
266
- secrets: secrets.map(s => ({
267
- file: s.file, line: s.line, type: s.type,
268
- severity: s.severity, is_env_interpolated: s.is_env_interpolated,
269
- })),
270
- rls: dbResult?.rls || [],
271
- framework: stack.framework,
272
- database: stack.database,
273
- },
274
- stack: {
275
- framework: stack.framework,
276
- database: stack.database,
277
- language: "typescript",
278
- hosting: "vercel",
279
- },
280
- };
281
- const capsuleResult = await (0, registry_1.runCapsule)(fixerContext, {
282
- mode: fixMode === "plan" ? "plan" : "apply",
283
- fixers: onlyFixers,
284
- dryRun: fixMode === "plan",
285
- }, (msg) => log(ciMode, msg));
286
- if (!ciMode) {
284
+ // ── Step 8: Recommendations ──
285
+ // NOTE: Capsule does NOT auto-fix code. We provide recommendations only.
286
+ // Applying fixes requires understanding of the target system — tables,
287
+ // relationships, business logic — and must be done by the customer's team.
288
+ if (!ciMode) {
289
+ const topFindings = metadata.findings || [];
290
+ if (topFindings.length > 0) {
287
291
  console.log("");
288
292
  console.log(" ══════════════════════════════════════");
289
- console.log(` CAPSULE ${fixMode === "plan" ? "PLAN" : "RESULTS"}`);
293
+ console.log(" RECOMMENDATIONS");
290
294
  console.log(" ══════════════════════════════════════");
291
- console.log(` Total actions: ${capsuleResult.totalActions}`);
292
- if (fixMode === "apply") {
293
- console.log(` Applied: ${capsuleResult.applied}`);
294
- console.log(` Failed: ${capsuleResult.failed}`);
295
- console.log(` Skipped: ${capsuleResult.skipped}`);
295
+ console.log(` ${topFindings.length} issues found. Top priorities:\n`);
296
+ const shown = topFindings.slice(0, 10);
297
+ for (const f of shown) {
298
+ const sev = f.severity === "critical" ? "\x1b[31mCRITICAL\x1b[0m"
299
+ : f.severity === "high" ? "\x1b[33mHIGH\x1b[0m"
300
+ : "\x1b[36mMEDIUM\x1b[0m";
301
+ console.log(` ${sev} ${f.title}`);
302
+ console.log(` \x1b[32m→ ${f.fix_suggestion}\x1b[0m`);
303
+ if (f.soc_control)
304
+ console.log(` SOC: ${f.soc_control}`);
305
+ console.log("");
296
306
  }
297
- console.log(` Manual pending: ${capsuleResult.manualPending}`);
298
- console.log(` Est. impact: +${capsuleResult.estimatedScoreImpact}% score`);
299
- console.log(` Proof hash: ${capsuleResult.proofHash.slice(0, 16)}...`);
300
- console.log(" ──────────────────────────────────────");
301
- // Print per-fixer summary
302
- for (const plan of capsuleResult.plans) {
303
- const icon = plan.actions.every(a => a.status === "applied") ? "✅"
304
- : plan.actions.some(a => a.status === "failed") ? "❌" : "📋";
305
- console.log(` ${icon} ${plan.nameHe}: ${plan.totalActions} actions (${plan.autoFixable} auto, ${plan.manualRequired} manual)`);
307
+ if (topFindings.length > 10) {
308
+ console.log(` ... and ${topFindings.length - 10} more. See full report.\n`);
306
309
  }
310
+ console.log(" ──────────────────────────────────────");
311
+ console.log(" ⚠ Capsule provides recommendations only.");
312
+ console.log(" Fixes require understanding of your system —");
313
+ console.log(" tables, relationships, and business logic.");
314
+ console.log(" Work with your team to apply changes safely.");
307
315
  console.log(" ══════════════════════════════════════\n");
308
- // Write fix plans to output dir
309
- if (capsuleResult.plans.length > 0) {
310
- const plansPath = (0, path_1.resolve)(outputDir, "nodata-fix-plan.json");
311
- (0, fs_1.writeFileSync)(plansPath, JSON.stringify(capsuleResult, null, 2), "utf-8");
312
- log(ciMode, `Fix plan saved: ${plansPath}`);
313
- // Write SQL migrations to files
314
- for (const plan of capsuleResult.plans) {
315
- for (const action of plan.actions) {
316
- if (action.type === "file-create" && action.target.includes("migrations/")) {
317
- const migPath = (0, path_1.resolve)(outputDir, action.target);
318
- const migDir = (0, path_1.resolve)(outputDir, "migrations");
319
- if (!(0, fs_1.existsSync)(migDir)) {
320
- const { mkdirSync } = require("fs");
321
- mkdirSync(migDir, { recursive: true });
322
- }
323
- (0, fs_1.writeFileSync)(migPath, action.content, "utf-8");
324
- log(ciMode, `Migration: ${migPath}`);
325
- }
326
- }
327
- }
328
- }
329
- }
330
- // Send notifications if configured
331
- if (config.notify && fixMode === "apply") {
332
- const notifyPayload = {
333
- event: capsuleResult.applied > 0 ? "fix-applied" : "scan-complete",
334
- timestamp: new Date().toISOString(),
335
- projectName: full.project_name || "unknown",
336
- projectHash: full.proof_hash?.slice(0, 16) || "",
316
+ // Save recommendations to file
317
+ const recsPath = (0, path_1.resolve)(outputDir, "nodata-recommendations.json");
318
+ (0, fs_1.writeFileSync)(recsPath, JSON.stringify({
319
+ generated_at: new Date().toISOString(),
337
320
  score: full.overall_score,
338
- previousScore: serverResponse.previous_score ?? null,
339
- delta: serverResponse.previous_score != null ? full.overall_score - serverResponse.previous_score : 0,
340
- critical: full.summary.critical_issues,
341
- high: full.summary.high_issues,
342
- medium: full.summary.medium_issues,
343
- fixesApplied: capsuleResult.applied,
344
- fixesFailed: capsuleResult.failed,
345
- scanId: activation.scan_id,
346
- proofHash: capsuleResult.proofHash,
347
- };
348
- await (0, registry_1.sendNotifications)(config, notifyPayload.event, notifyPayload, (msg) => log(ciMode, msg));
321
+ total_findings: topFindings.length,
322
+ disclaimer: "These are recommendations only. Capsule does not modify your code. Fixes require understanding of your system architecture, database schema, and business logic. Work with your development team to implement changes safely.",
323
+ recommendations: topFindings,
324
+ }, null, 2), "utf-8");
325
+ log(ciMode, `Recommendations: ${recsPath}`);
349
326
  }
350
327
  }
351
328
  // ── CI mode: exit code ──
@@ -392,14 +369,16 @@ function loadOrCreateConfig(projectDir, overrides) {
392
369
  }
393
370
  function printHelp() {
394
371
  console.log(`
395
- NoData Guard v${VERSION} — Security Scanner + Auto-Remediation Capsule
372
+ NoData Guard v${VERSION} — Security Scanner + Recommendations
373
+
374
+ Scans your project locally for security issues and provides
375
+ actionable recommendations. Your code never leaves your machine.
376
+ Capsule does NOT modify your code — only you and your team can.
396
377
 
397
378
  Usage:
398
- npx nodata-guard --license-key NDC-XXXX # Scan only
399
- npx nodata-guard --license-key NDC-XXXX --fix-plan # Scan + show fix plan
400
- npx nodata-guard --license-key NDC-XXXX --fix # Scan + apply fixes
401
- npx nodata-guard --license-key NDC-XXXX --schedule weekly # Setup CI schedule
402
- npx nodata-guard --license-key NDC-XXXX --db $DATABASE_URL --fix # Full scan + fix
379
+ npx nodata-guard --license-key NDC-XXXX # Scan + recommend
380
+ npx nodata-guard --license-key NDC-XXXX --db $DATABASE_URL # Full scan (code + DB)
381
+ npx nodata-guard --license-key NDC-XXXX --schedule weekly # Setup CI schedule
403
382
 
404
383
  Scan Options:
405
384
  --license-key <key> NoData license key (or set NDC_LICENSE env var)
@@ -410,13 +389,6 @@ function printHelp() {
410
389
  --fail-on <level> Exit 1 if issues at: critical | high | medium
411
390
  --skip-send Don't send metadata to NoData
412
391
 
413
- Capsule Options:
414
- --fix-plan Generate fix plan (dry-run, no changes)
415
- --fix Apply all auto-fixable remediation
416
- --fix-only <fixers> Only run specific fixers (comma-separated)
417
- Fixers: pii-encrypt, rls, secrets, routes-auth,
418
- headers, csrf, rate-limit, gitignore
419
-
420
392
  Schedule Options:
421
393
  --schedule <preset> Install CI workflow: daily | weekly | monthly
422
394
  --ci-provider <name> CI provider: github-actions | gitlab-ci | bitbucket | auto
@@ -425,31 +397,39 @@ function printHelp() {
425
397
  Configure in .nodata-guard.json → notify: { email, webhook, slack, telegram }
426
398
 
427
399
  Output files:
428
- nodata-full-report.json Full report — STAYS LOCAL
429
- nodata-metadata-only.json Metadata only — sent to NoData
430
- nodata-fix-plan.json Fix plan with actions
431
- migrations/*.sql Generated SQL migrations
400
+ nodata-full-report.json Full report — STAYS LOCAL
401
+ nodata-metadata-only.json Metadata only — sent to dashboard
402
+ nodata-recommendations.json Prioritized recommendations
432
403
 
433
- What we NEVER receive:
434
- Data values, emails, phones, passwords, source code, connection strings.
404
+ What we provide:
405
+ Scan find weak points (PII, routes, secrets, encryption)
406
+ ✓ Recommend — prioritized actions with SOC control mapping
407
+ ✓ Prove — cryptographic proof chain of scan results
408
+ ✓ Monitor — track score over time via dashboard
409
+
410
+ What we NEVER do:
411
+ ✗ Modify your code, database, or configuration
412
+ ✗ Receive data values, source code, or credentials
413
+
414
+ Important:
415
+ Recommendations require understanding of YOUR system —
416
+ tables, relationships, business logic. Work with your team
417
+ to implement changes safely.
435
418
 
436
419
  Examples:
437
- # Quick scan
420
+ # Scan and get recommendations
438
421
  npx nodata-guard --license-key NDC-XXXX
439
422
 
440
- # Full scan + DB probe + fix
441
- npx nodata-guard --license-key NDC-XXXX --db $DATABASE_URL --fix
442
-
443
- # Only fix security headers and CSRF
444
- npx nodata-guard --license-key NDC-XXXX --fix --fix-only headers,csrf
423
+ # Full scan with DB probe
424
+ npx nodata-guard --license-key NDC-XXXX --db $DATABASE_URL
445
425
 
446
426
  # Setup weekly CI scan with GitHub Actions
447
427
  npx nodata-guard --license-key NDC-XXXX --schedule weekly
448
428
 
449
- # CI pipeline
429
+ # CI pipeline — fail on critical issues
450
430
  npx nodata-guard --ci --fail-on critical
451
431
 
452
- Documentation: https://nodatachat.com/guard
432
+ Documentation: https://nodatacapsule.com/guard
453
433
  `);
454
434
  }
455
435
  main().catch((err) => {
@@ -156,7 +156,7 @@ async function sendNotifications(config, event, payload, onLog) {
156
156
  if (config.notify.email?.length) {
157
157
  for (const email of config.notify.email) {
158
158
  try {
159
- await fetch("https://nodatachat.com/api/guard/notify", {
159
+ await fetch("https://nodatacapsule.com/api/guard/notify", {
160
160
  method: "POST",
161
161
  headers: { "Content-Type": "application/json" },
162
162
  body: JSON.stringify({ channel: "email", to: email, payload }),
package/dist/reporter.js CHANGED
@@ -123,8 +123,35 @@ function generateReports(input) {
123
123
  critical: criticalSecrets,
124
124
  high: highSecrets + plaintextPII,
125
125
  medium: medSecrets,
126
- fixes_available: plaintextPII, // each plaintext field has a migration fix
126
+ recommendations_available: plaintextPII, // each plaintext field has a recommendation
127
127
  },
128
+ // Fix suggestions — safe to send (just recommendation text, no code/values)
129
+ findings: [
130
+ ...allPII.filter(f => !f.encrypted).map(f => ({
131
+ severity: "high",
132
+ category: "pii",
133
+ rule_id: `PII_${f.pii_type.toUpperCase()}`,
134
+ title: `${f.table}.${f.column} — ${f.pii_type} stored in plaintext`,
135
+ fix_suggestion: `Add AES-256-GCM encryption to ${f.table}.${f.column} via Capsule field permissions`,
136
+ soc_control: "CC6.7",
137
+ })),
138
+ ...(input.code?.secrets.filter(s => !s.is_env_interpolated) || []).map(s => ({
139
+ severity: s.severity,
140
+ category: "secrets",
141
+ rule_id: `SECRET_${s.type.toUpperCase().replace(/-/g, "_")}`,
142
+ title: `Hardcoded ${s.type} in ${s.file}:${s.line}`,
143
+ fix_suggestion: `Move to .env and encrypt with @nodatachat/protect`,
144
+ soc_control: "CC6.1",
145
+ })),
146
+ ...(input.code?.routes.filter(r => !r.has_auth) || []).slice(0, 20).map(r => ({
147
+ severity: "high",
148
+ category: "auth",
149
+ rule_id: "ROUTE_NO_AUTH",
150
+ title: `Unprotected route: ${r.path}`,
151
+ fix_suggestion: `Add authentication middleware (withAuth or API key check)`,
152
+ soc_control: "CC6.3",
153
+ })),
154
+ ],
128
155
  proof_hash: proofHash,
129
156
  privacy: {
130
157
  contains_data_values: false,
@@ -176,7 +203,7 @@ function generateReports(input) {
176
203
  critical_issues: criticalSecrets,
177
204
  high_issues: highSecrets + plaintextPII,
178
205
  medium_issues: medSecrets,
179
- fixes_available: plaintextPII,
206
+ recommendations_available: plaintextPII,
180
207
  },
181
208
  proof_hash: proofHash,
182
209
  metadata_preview: metadata,
package/dist/types.d.ts CHANGED
@@ -84,7 +84,7 @@ export interface FullReport {
84
84
  critical_issues: number;
85
85
  high_issues: number;
86
86
  medium_issues: number;
87
- fixes_available: number;
87
+ recommendations_available: number;
88
88
  };
89
89
  proof_hash: string;
90
90
  metadata_preview: MetadataReport;
@@ -140,8 +140,16 @@ export interface MetadataReport {
140
140
  critical: number;
141
141
  high: number;
142
142
  medium: number;
143
- fixes_available: number;
143
+ recommendations_available: number;
144
144
  };
145
+ findings: Array<{
146
+ severity: "critical" | "high" | "medium" | "low";
147
+ category: string;
148
+ rule_id: string;
149
+ title: string;
150
+ fix_suggestion: string;
151
+ soc_control: string;
152
+ }>;
145
153
  proof_hash: string;
146
154
  privacy: {
147
155
  contains_data_values: false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nodatachat/guard",
3
- "version": "2.0.0",
3
+ "version": "2.2.0",
4
4
  "description": "NoData Guard — continuous security scanner. Runs locally, reports only metadata. Your data never leaves your machine.",
5
5
  "main": "./dist/cli.js",
6
6
  "types": "./dist/cli.d.ts",
@@ -49,7 +49,7 @@
49
49
  "devsecops"
50
50
  ],
51
51
  "license": "SEE LICENSE IN LICENSE.md",
52
- "homepage": "https://nodatachat.com/guard",
52
+ "homepage": "https://nodatacapsule.com/guard",
53
53
  "repository": {
54
54
  "type": "git",
55
55
  "url": "https://github.com/nodatachat/guard"
@@ -57,5 +57,5 @@
57
57
  "bugs": {
58
58
  "url": "https://github.com/nodatachat/guard/issues"
59
59
  },
60
- "author": "NoDataChat <support@nodatachat.com>"
60
+ "author": "Capsule <support@nodatacapsule.com>"
61
61
  }