logshield-cli 0.4.2 → 0.4.4

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/CHANGELOG.md CHANGED
@@ -1,100 +1,132 @@
1
- # Changelog
2
-
3
- ## v0.4.2
4
-
5
- ### Fixed
6
-
7
- - CLI errors are now written to stderr (CI-safe piping)
8
- - JSON output is newline-terminated
9
- - URL redaction is no longer overly aggressive; only credentials and sensitive parameters are redacted
10
- - PASSWORD redaction preserves original delimiter and spacing
11
- - Improved dry-run reporting consistency
12
- - Added contract tests for CLI output and URL behavior
13
-
14
- ## v0.4.1
15
-
16
- ### Fixed
17
-
18
- - Prevented secret leakage in `--json` output by removing raw match values from the public result shape
19
- - Forwarded `--dry-run` into the engine to ensure consistent, future-proof behavior
20
-
21
- ### Improved
22
-
23
- - Expanded credential detection for common API key variants (`api_key`, `api-key`, `apikey`) and `Authorization: Bearer ...`
24
- - Hardened AWS secret key strict detection to reduce false positives while keeping strict mode safe
25
-
26
- ### Notes
27
-
28
- - No breaking changes
29
- - No new features
30
- - Stability and safety hardening release
31
-
32
- ## v0.4.0
33
-
34
- ### Changed
35
-
36
- - License updated to Apache-2.0
37
- - README, website, and blog content aligned to reflect the new license and current project state
38
-
39
- ### Notes
40
-
41
- - No engine or CLI behavior changes
42
- - No breaking changes
43
-
44
- ## v0.3.6
45
-
46
- ### Fixed
47
-
48
- - `--summary` output now correctly written to stderr (safe for piping & redirects)
49
-
50
- ### Improved
51
-
52
- - CLI documentation clarity
53
-
54
- ### Notes
55
-
56
- - No breaking changes
57
-
58
- ## v0.3.5
59
-
60
- ### Fixed
61
-
62
- - Corrected CLI version injection in built CJS output
63
- - Ensured published npm package reflects actual CLI version
64
-
65
- ### Improved
66
-
67
- - Deterministic `--dry-run` report formatting (aligned, CI-safe)
68
- - Dry-run output now strictly non-contextual and stdout-only
69
-
70
- ### Notes
71
-
72
- - No engine or rule behavior changes
73
- - Pure CLI/build correctness release
74
-
75
- ---
76
-
77
- ## v0.3.4
78
-
79
- ### Fixed
80
-
81
- - README CI badge link on npmjs.com
82
-
83
- ---
84
-
85
- ## v0.3.3
86
-
87
- ### Added
88
-
89
- - `--dry-run` mode to detect secrets without modifying output
90
- - CI-friendly detection workflow (`--dry-run --fail-on-detect`)
91
-
92
- ### Improved
93
-
94
- - CLI UX consistency
95
- - README documentation clarity
96
-
97
- ### Notes
98
-
99
- - No breaking changes
100
- - Engine behavior unchanged
1
+ # Changelog
2
+
3
+ ## v0.4.4
4
+
5
+ ### Fixed
6
+
7
+ - Expanded PASSWORD redaction to cover quoted values (including spaces) and JSON forms (`"password": "..."`)
8
+ - Expanded DB URL credential redaction to cover additional common schemes (`redis://`, `mssql://`, and variants)
9
+
10
+ ### Notes
11
+
12
+ - No breaking changes
13
+ - Behavior is still deterministic; this release reduces false negatives in common log formats
14
+
15
+ ## v0.4.3
16
+
17
+ ### Fixed
18
+
19
+ - Prevented API key redaction from corrupting header names (`x-api-key`)
20
+ - Preserved key labels when redacting `api_key=...` values
21
+ - Corrected CLI exit code for invalid flag combinations (`--json --dry-run` now exits with code 2)
22
+
23
+ ### Improved
24
+
25
+ - Deterministic and aligned `--summary` output (alphabetical, indented)
26
+ - Hardened CLI behavior with end-to-end golden tests
27
+ - Strengthened regression coverage for rule overlap and precedence
28
+
29
+ ### Notes
30
+
31
+ - No breaking changes
32
+ - No new features
33
+ - Hardening and correctness release
34
+
35
+ ## v0.4.2
36
+
37
+ ### Fixed
38
+
39
+ - CLI errors are now written to stderr (CI-safe piping)
40
+ - JSON output is newline-terminated
41
+ - URL redaction is no longer overly aggressive; only credentials and sensitive parameters are redacted
42
+ - PASSWORD redaction preserves original delimiter and spacing
43
+ - Improved dry-run reporting consistency
44
+ - Added contract tests for CLI output and URL behavior
45
+
46
+ ## v0.4.1
47
+
48
+ ### Fixed
49
+
50
+ - Prevented secret leakage in `--json` output by removing raw match values from the public result shape
51
+ - Forwarded `--dry-run` into the engine to ensure consistent, future-proof behavior
52
+
53
+ ### Improved
54
+
55
+ - Expanded credential detection for common API key variants (`api_key`, `api-key`, `apikey`) and `Authorization: Bearer ...`
56
+ - Hardened AWS secret key strict detection to reduce false positives while keeping strict mode safe
57
+
58
+ ### Notes
59
+
60
+ - No breaking changes
61
+ - No new features
62
+ - Stability and safety hardening release
63
+
64
+ ## v0.4.0
65
+
66
+ ### Changed
67
+
68
+ - License updated to Apache-2.0
69
+ - README, website, and blog content aligned to reflect the new license and current project state
70
+
71
+ ### Notes
72
+
73
+ - No engine or CLI behavior changes
74
+ - No breaking changes
75
+
76
+ ## v0.3.6
77
+
78
+ ### Fixed
79
+
80
+ - `--summary` output now correctly written to stderr (safe for piping & redirects)
81
+
82
+ ### Improved
83
+
84
+ - CLI documentation clarity
85
+
86
+ ### Notes
87
+
88
+ - No breaking changes
89
+
90
+ ## v0.3.5
91
+
92
+ ### Fixed
93
+
94
+ - Corrected CLI version injection in built CJS output
95
+ - Ensured published npm package reflects actual CLI version
96
+
97
+ ### Improved
98
+
99
+ - Deterministic `--dry-run` report formatting (aligned, CI-safe)
100
+ - Dry-run output now strictly non-contextual and stdout-only
101
+
102
+ ### Notes
103
+
104
+ - No engine or rule behavior changes
105
+ - Pure CLI/build correctness release
106
+
107
+ ---
108
+
109
+ ## v0.3.4
110
+
111
+ ### Fixed
112
+
113
+ - README CI badge link on npmjs.com
114
+
115
+ ---
116
+
117
+ ## v0.3.3
118
+
119
+ ### Added
120
+
121
+ - `--dry-run` mode to detect secrets without modifying output
122
+ - CI-friendly detection workflow (`--dry-run --fail-on-detect`)
123
+
124
+ ### Improved
125
+
126
+ - CLI UX consistency
127
+ - README documentation clarity
128
+
129
+ ### Notes
130
+
131
+ - No breaking changes
132
+ - Engine behavior unchanged
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![npm downloads](https://img.shields.io/npm/dm/logshield-cli)](https://www.npmjs.com/package/logshield-cli)
5
5
  [![CI](https://github.com/afria85/LogShield/actions/workflows/ci.yml/badge.svg)](https://github.com/afria85/LogShield/actions/workflows/ci.yml)
6
6
 
7
- Your logs already contain secrets. You just dont see them.
7
+ Your logs already contain secrets. You just don't see them.
8
8
 
9
9
  LogShield is a small CLI that automatically redacts secrets from logs **before**
10
10
  you paste them into CI, GitHub issues, Slack, or send them to third-party support.
@@ -55,22 +55,28 @@ Use LogShield whenever logs leave your system:
55
55
 
56
56
  ```bash
57
57
  # Preview what would be redacted (does not modify output)
58
- echo "email=test@example.com token=sk_live_123" | logshield scan --dry-run
58
+ echo "email=test@example.com Authorization: Bearer abcdefghijklmnop" | logshield scan --dry-run
59
59
  ```
60
60
 
61
61
  ```
62
62
  logshield (dry-run)
63
63
  Detected 2 redactions:
64
- EMAIL x1
65
- STRIPE_SECRET_KEY x1
64
+ AUTH_BEARER x1
65
+ EMAIL x1
66
66
 
67
67
  No output was modified.
68
68
  Use without --dry-run to apply.
69
69
  ```
70
70
 
71
+ Notes:
72
+
73
+ - The report is printed to stdout
74
+ - No log content is echoed
75
+ - Output is deterministic and CI-safe
76
+
71
77
  ```bash
72
78
  # Enforce redaction (sanitized output)
73
- echo "email=test@example.com token=sk_live_123" | logshield scan
79
+ echo "email=test@example.com Authorization: Bearer abcdefghijklmnop" | logshield scan
74
80
  ```
75
81
 
76
82
  - Prefer `--dry-run` first in CI to verify you are not over-redacting.
@@ -140,8 +146,8 @@ Examples:
140
146
 
141
147
  ```
142
148
  <REDACTED_PASSWORD>
143
- <REDACTED_API_KEY_HEADER>
144
- <REDACTED_AUTH_BEARER>
149
+ <REDACTED_API_KEY>
150
+ <REDACTED_TOKEN>
145
151
  <REDACTED_EMAIL>
146
152
  ```
147
153
 
@@ -247,8 +253,8 @@ cat app.log | logshield scan --dry-run
247
253
 
248
254
  ```
249
255
  logshield (dry-run)
250
- Detected 5 redactions:
251
- AUTH_BEARER x2
256
+ Detected 4 redactions:
257
+ AUTH_BEARER x1
252
258
  EMAIL x1
253
259
  OAUTH_ACCESS_TOKEN x1
254
260
  PASSWORD x1
@@ -345,10 +351,16 @@ Example:
345
351
 
346
352
  ```
347
353
  LogShield Summary
348
- PASSWORD: 2
349
- API_KEY_HEADER: 1
354
+ API_KEY_HEADER x1
355
+ PASSWORD x2
350
356
  ```
351
357
 
358
+ Notes:
359
+
360
+ - Sanitized log output is written to stdout
361
+ - The summary is written to stderr
362
+ - Rules are sorted alphabetically
363
+
352
364
  ---
353
365
 
354
366
  ## JSON output
@@ -362,17 +374,18 @@ logshield scan --json < logs.txt
362
374
  Notes:
363
375
 
364
376
  - `--json` **cannot** be combined with `--dry-run`
365
- - Output schema is stable within v0.4.x
377
+ - Usage errors exit with code `2`
378
+ - Output is always newline-terminated
366
379
 
367
380
  ---
368
381
 
369
382
  ## Exit codes
370
383
 
371
- | Code | Meaning |
372
- | ---: | ------------------------------------ |
373
- | 0 | Success / no detection |
374
- | 1 | Detection found (`--fail-on-detect`) |
375
- | 2 | Runtime or input error |
384
+ | Code | Meaning |
385
+ | ---: | --------------------------------------------- |
386
+ | 0 | Success (detection does not change exit code) |
387
+ | 1 | Detection found (`--fail-on-detect`) |
388
+ | 2 | Runtime or input error |
376
389
 
377
390
  ---
378
391
 
@@ -380,13 +393,13 @@ Notes:
380
393
 
381
394
  Depending on rules and mode:
382
395
 
383
- - Passwords
396
+ - Passwords (supports quoted and JSON forms)
384
397
  - API key headers
385
398
  - Authorization bearer tokens
386
399
  - JWTs
387
400
  - Emails
388
401
  - URLs with embedded credentials
389
- - Database credentials
402
+ - Database credentials (including redis:// and mssql://)
390
403
  - Cloud provider credentials
391
404
  - Credit card numbers (Luhn-validated)
392
405
 
@@ -87,33 +87,25 @@ __export(summary_exports, {
87
87
  printSummary: () => printSummary
88
88
  });
89
89
  function printSummary(matches) {
90
- if (!matches || matches.length === 0) {
91
- process.stderr.write("logshield: no redactions detected\n");
90
+ if (!matches.length) {
91
+ process.stderr.write("LogShield Summary\n(no redactions detected)\n");
92
92
  return;
93
93
  }
94
- const counter = {};
94
+ const counts = {};
95
95
  for (const m of matches) {
96
- counter[m.rule] = (counter[m.rule] || 0) + 1;
96
+ counts[m.rule] = (counts[m.rule] ?? 0) + 1;
97
97
  }
98
- const entries = Object.entries(counter).map(([rule, count]) => ({ rule, count })).sort((a, b) => {
99
- if (b.count !== a.count) return b.count - a.count;
100
- return a.rule.localeCompare(b.rule);
101
- });
102
- const maxLen = Math.max(...entries.map((e) => e.rule.length));
103
- const total = matches.length;
104
- const label = total === 1 ? "redaction" : "redactions";
105
- process.stderr.write(`logshield summary: ${total} ${label}
98
+ const rules = Object.keys(counts).sort((a, b) => a.localeCompare(b));
99
+ const maxNameLen = Math.max(...rules.map((r) => r.length));
100
+ process.stderr.write("LogShield Summary\n");
101
+ for (const rule of rules) {
102
+ const padded = rule.padEnd(maxNameLen, " ");
103
+ process.stderr.write(` ${padded} x${counts[rule]}
106
104
  `);
107
- for (const { rule, count } of entries) {
108
- process.stderr.write(
109
- ` ${rule.padEnd(maxLen)} x${count}
110
- `
111
- );
112
105
  }
113
106
  }
114
107
  var init_summary = __esm({
115
108
  "src/cli/summary.ts"() {
116
- "use strict";
117
109
  }
118
110
  });
119
111
 
@@ -208,15 +200,38 @@ var init_credentials = __esm({
208
200
  // Examples:
209
201
  // password=secret -> password=<REDACTED_PASSWORD>
210
202
  // Password : 123 -> Password : <REDACTED_PASSWORD>
211
- pattern: /\b(password)(\s*[:=]\s*)([^\s]+)/gi,
212
- replace: (_match, _ctx, groups) => `${groups[0]}${groups[1]}<REDACTED_PASSWORD>`
203
+ // Supports quoted keys/values and JSON forms:
204
+ // password="secret value" -> password="<REDACTED_PASSWORD>"
205
+ // "password": "secret value" -> "password": "<REDACTED_PASSWORD>"
206
+ // NOTE: for unquoted values, we stop at whitespace and common JSON delimiters.
207
+ pattern: /\b(["']?password["']?)(\s*[:=]\s*)(?:(["'])([^"'\r\n]*?)\3|([^\s,}\]]+))/gi,
208
+ replace: (_match, _ctx, groups) => {
209
+ const key = groups[0];
210
+ const delim = groups[1];
211
+ const quote = groups[2];
212
+ if (quote) {
213
+ return `${key}${delim}${quote}<REDACTED_PASSWORD>${quote}`;
214
+ }
215
+ return `${key}${delim}<REDACTED_PASSWORD>`;
216
+ }
213
217
  },
214
218
  // DB URL credential: postgres://user:pass@host
215
219
  {
216
220
  name: "DB_URL_CREDENTIAL",
217
- pattern: /\b(postgres|mysql|mongodb):\/\/([^:\s]+):([^@\s]+)@/gi,
221
+ // Support the most common DB/cache schemes.
222
+ // This focuses only on the user:pass@ authority portion.
223
+ pattern: /\b(postgres(?:ql)?|mysql|mariadb|mongodb(?:\+srv)?|redis|rediss|mssql|sqlserver):\/\/([^:\s]+):([^@\s]+)@/gi,
218
224
  replace: (_match, _ctx, groups) => `${groups[0]}://${groups[1]}:<REDACTED_PASSWORD>@`
219
225
  },
226
+ // x-api-key: ....
227
+ // IMPORTANT: this must run BEFORE the generic API_KEY rule. Otherwise the
228
+ // generic API_KEY rule can match the "api-key: <value>" substring first and
229
+ // corrupt the header name (e.g. "x-api-key" -> "x-").
230
+ {
231
+ name: "API_KEY_HEADER",
232
+ pattern: /\bx-api-key\s*:\s*["']?[A-Za-z0-9_\-]{16,}["']?\b/gi,
233
+ replace: () => "x-api-key: <REDACTED_API_KEY>"
234
+ },
220
235
  /**
221
236
  * API key (common variants):
222
237
  * - apiKey=...
@@ -224,23 +239,19 @@ var init_credentials = __esm({
224
239
  * - api-key: ...
225
240
  * - apikey=...
226
241
  * Supports '=' or ':' and optional quotes/spaces.
242
+ *
243
+ * NOTE:
244
+ * Do NOT try to handle "Authorization: Bearer ..." here; that causes overlap
245
+ * with token rules. Token redaction is handled in tokens.ts.
227
246
  */
228
247
  {
229
248
  name: "API_KEY",
230
- pattern: /\bapi(?:[_-]?key)\s*[:=]\s*["']?([A-Za-z0-9_\-]{16,})["']?\b/gi,
231
- replace: () => "<REDACTED_API_KEY>"
232
- },
233
- // x-api-key: ....
234
- {
235
- name: "API_KEY_HEADER",
236
- pattern: /\bx-api-key\s*:\s*["']?[A-Za-z0-9_\-]{16,}["']?\b/gi,
237
- replace: () => "x-api-key: <REDACTED_API_KEY>"
238
- },
239
- // authorization: Bearer ...
240
- {
241
- name: "AUTHORIZATION_BEARER",
242
- pattern: /\bauthorization\s*:\s*bearer\s+([A-Za-z0-9._\-]{16,})\b/gi,
243
- replace: () => "authorization: Bearer <REDACTED_TOKEN>"
249
+ // Preserve the key label + delimiter, redact only the value.
250
+ // Examples:
251
+ // api_key=abcdef... -> api_key=<REDACTED_API_KEY>
252
+ // api-key: "abcdef..." -> api-key: "<REDACTED_API_KEY>"
253
+ pattern: /\b(api(?:[_-]?key)\s*[:=]\s*["']?)([A-Za-z0-9_\-]{16,})(["']?)\b/gi,
254
+ replace: (_match, _ctx, groups) => `${groups[0]}<REDACTED_API_KEY>${groups[2]}`
244
255
  }
245
256
  ];
246
257
  }
@@ -512,7 +523,7 @@ var { printSummary: printSummary2 } = (init_summary(), __toCommonJS(summary_expo
512
523
  var { sanitizeLog: sanitizeLog2 } = (init_sanitizeLog(), __toCommonJS(sanitizeLog_exports));
513
524
  var rawArgs = process.argv.slice(2).map((arg) => arg === "-h" ? "--help" : arg);
514
525
  function getVersion() {
515
- return true ? "0.4.2" : "unknown";
526
+ return true ? "0.4.4" : "unknown";
516
527
  }
517
528
  function printHelp() {
518
529
  process.stdout.write(`Usage: logshield scan [file]
@@ -580,6 +591,10 @@ function renderDryRunReport(matches) {
580
591
  process.stdout.write("No output was modified.\n");
581
592
  process.stdout.write("Use without --dry-run to apply.\n");
582
593
  }
594
+ function exitUsageError(message) {
595
+ writeErr(message.endsWith("\n") ? message : message + "\n");
596
+ process.exit(2);
597
+ }
583
598
  async function main() {
584
599
  if (rawArgs.length === 0 || rawArgs.includes("--help")) {
585
600
  printHelp();
@@ -593,8 +608,7 @@ async function main() {
593
608
  const { flags, positionals } = parseArgs(rawArgs);
594
609
  const command = positionals[0];
595
610
  if (command !== "scan") {
596
- writeErr("Unknown command\n");
597
- process.exit(1);
611
+ exitUsageError("Unknown command");
598
612
  }
599
613
  const file = positionals[1];
600
614
  const strict = flags.has("--strict");
@@ -606,16 +620,13 @@ async function main() {
606
620
  const stdinAuto = isStdinPiped();
607
621
  const useStdin = stdinFlag || stdinAuto;
608
622
  if (useStdin && file) {
609
- writeErr("Cannot read from both STDIN and file\n");
610
- process.exit(1);
623
+ exitUsageError("Cannot read from both STDIN and file");
611
624
  }
612
625
  if (dryRun && json) {
613
- writeErr("--dry-run cannot be used with --json\n");
614
- process.exit(1);
626
+ exitUsageError("--dry-run cannot be used with --json");
615
627
  }
616
628
  if (json && summary) {
617
- writeErr("--summary cannot be used with --json\n");
618
- process.exit(1);
629
+ exitUsageError("--summary cannot be used with --json");
619
630
  }
620
631
  try {
621
632
  const input = await readInput2(useStdin ? void 0 : file);
package/dist/features.jsx CHANGED
@@ -45,7 +45,7 @@ function FeaturesPage() {
45
45
  },
46
46
  {
47
47
  title: "No Tracking",
48
- description: "We use privacy-friendly analytics (Plausible) with no cookies or personal data collection."
48
+ description: "We use minimal Google Analytics configuration for basic traffic insights."
49
49
  }
50
50
  ]
51
51
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "logshield-cli",
3
- "version": "0.4.2",
3
+ "version": "0.4.4",
4
4
  "license": "Apache-2.0",
5
5
  "type": "commonjs",
6
6
  "bin": {
@@ -20,7 +20,8 @@
20
20
  "typecheck": "tsc -p tsconfig.core.json && tsc -p tsconfig.cli.json --noEmit",
21
21
  "pretest": "npm run build",
22
22
  "test": "vitest",
23
- "prepublishOnly": "npm run build"
23
+ "prepublish:check": "npm run typecheck && npm test",
24
+ "prepublishOnly": "npm run prepublish:check"
24
25
  },
25
26
  "devDependencies": {
26
27
  "@types/node": "^25.0.3",
package/dist/privacy.html DELETED
@@ -1,217 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Privacy Policy - LogShield</title>
7
- <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
8
- <style>
9
- * { margin: 0; padding: 0; box-sizing: border-box; }
10
- body {
11
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
12
- line-height: 1.6;
13
- color: #333;
14
- background: linear-gradient(to bottom right, #f8fafc, #e0f2fe);
15
- min-height: 100vh;
16
- padding: 20px;
17
- }
18
- .container {
19
- max-width: 800px;
20
- margin: 0 auto;
21
- background: white;
22
- padding: 40px;
23
- border-radius: 12px;
24
- box-shadow: 0 4px 6px rgba(0,0,0,0.1);
25
- }
26
- .back-button {
27
- display: inline-flex;
28
- align-items: center;
29
- gap: 8px;
30
- padding: 10px 20px;
31
- background: #3b82f6;
32
- color: white;
33
- text-decoration: none;
34
- border-radius: 6px;
35
- font-size: 14px;
36
- font-weight: 500;
37
- transition: background 0.2s;
38
- margin-bottom: 30px;
39
- }
40
- .back-button:hover { background: #2563eb; }
41
- h1 { color: #1e40af; font-size: 32px; margin-bottom: 10px; }
42
- .last-updated { color: #6b7280; font-size: 14px; margin-bottom: 30px; }
43
- h2 { color: #3b82f6; font-size: 24px; margin: 30px 0 15px; }
44
- h3 { font-size: 18px; color: #1f2937; margin: 20px 0 10px; }
45
- p, li { margin-bottom: 15px; color: #4b5563; }
46
- ul { margin-left: 30px; }
47
- strong { color: #1f2937; }
48
- .highlight { background: #fef3c7; padding: 15px; border-left: 4px solid #f59e0b; margin: 20px 0; border-radius: 4px; }
49
- .entity-info { background: #f0f9ff; padding: 15px; border-left: 4px solid #3b82f6; margin: 20px 0; border-radius: 4px; }
50
- @media (max-width: 768px) {
51
- .container { padding: 20px; }
52
- h1 { font-size: 24px; }
53
- h2 { font-size: 20px; }
54
- }
55
- </style>
56
- </head>
57
- <body>
58
- <div class="container">
59
- <a href="/" class="back-button">
60
- <svg width="16" height="16" viewBox="0 0 16 16" fill="none">
61
- <path d="M10 12L6 8L10 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
62
- </svg>
63
- Back to LogShield
64
- </a>
65
-
66
- <h1>Privacy Policy</h1>
67
- <p class="last-updated"><strong>Last updated:</strong> December 10, 2025</p>
68
-
69
- <!-- CRITICAL: Entity Information for Paddle -->
70
- <div class="entity-info">
71
- <strong>Data Controller:</strong> This Privacy Policy describes how <strong>Hendra Afria</strong>, operating as <strong>LogShield</strong>, collects, uses, and protects your information when you use our log sanitization service.
72
- </div>
73
-
74
- <div class="highlight">
75
- <strong>&#128274; Privacy First:</strong> LogShield processes all your log data entirely in your browser. We never see, store, or transmit your sensitive data to our servers.
76
- </div>
77
-
78
- <h2>1. Information We Collect</h2>
79
-
80
- <h3>a) Account Information</h3>
81
- <ul>
82
- <li>Email address (for account creation and communication)</li>
83
- <li>Display name (optional)</li>
84
- <li>Payment information (processed securely by Paddle, we never see full card details)</li>
85
- </ul>
86
-
87
- <h3>b) Usage Data</h3>
88
- <ul>
89
- <li>Anonymous analytics via Plausible (privacy-friendly, GDPR-compliant)</li>
90
- <li>Feature usage statistics (aggregated, non-identifying)</li>
91
- <li>Error logs for debugging (no personal data included)</li>
92
- </ul>
93
-
94
- <h3>c) What We DON'T Collect</h3>
95
- <ul>
96
- <li><strong>Your log data</strong> - processed 100% client-side in your browser</li>
97
- <li><strong>Tracking cookies</strong> - we don't use them</li>
98
- <li><strong>Browsing history</strong></li>
99
- <li><strong>Device fingerprints</strong></li>
100
- </ul>
101
-
102
- <h2>2. How We Use Your Information</h2>
103
- <p>We use collected information solely to:</p>
104
- <ul>
105
- <li>Provide and improve the Service</li>
106
- <li>Process payments and manage subscriptions</li>
107
- <li>Send important service updates and security alerts</li>
108
- <li>Respond to support requests</li>
109
- <li>Analyze usage patterns (anonymously) to improve features</li>
110
- </ul>
111
-
112
- <h2>3. Client-Side Processing</h2>
113
- <p><strong>This is our core privacy commitment:</strong></p>
114
- <p>All log sanitization happens entirely in your browser using JavaScript. When you paste or upload logs:</p>
115
- <ul>
116
- <li>&#x2705; Data stays in your browser's memory</li>
117
- <li>&#x2705; Sanitization patterns are applied locally</li>
118
- <li>&#x2705; No network transmission of your log content</li>
119
- <li>&#x2705; No server-side storage of your logs</li>
120
- <li>&#x2705; Data cleared when you close the tab</li>
121
- </ul>
122
-
123
- <h2>4. Third-Party Services</h2>
124
-
125
- <h3>Paddle (Payment Processing)</h3>
126
- <ul>
127
- <li>Handles all payment transactions</li>
128
- <li>PCI-DSS Level 1 compliant</li>
129
- <li>We never see your full credit card details</li>
130
- <li>Privacy policy: <a href="https://paddle.com/privacy" style="color: #3b82f6;">paddle.com/privacy</a></li>
131
- </ul>
132
-
133
- <h3>Plausible Analytics</h3>
134
- <ul>
135
- <li>Privacy-friendly, GDPR-compliant analytics</li>
136
- <li>No cookies, no personal data collection</li>
137
- <li>Only tracks aggregated page views and referrers</li>
138
- <li>Open source: <a href="https://plausible.io" style="color: #3b82f6;">plausible.io</a></li>
139
- </ul>
140
-
141
- <h3>Vercel (Hosting)</h3>
142
- <ul>
143
- <li>Hosts our website infrastructure</li>
144
- <li>Standard server logs only (IP, user agent, timestamp)</li>
145
- <li>Privacy policy: <a href="https://vercel.com/legal/privacy-policy" style="color: #3b82f6;">vercel.com/legal/privacy-policy</a></li>
146
- </ul>
147
-
148
- <h2>5. Data Storage and Security</h2>
149
- <p><strong>What we store:</strong></p>
150
- <ul>
151
- <li>Account details (encrypted at rest)</li>
152
- <li>Subscription status</li>
153
- <li>User preferences (in browser localStorage)</li>
154
- </ul>
155
-
156
- <p><strong>What we don't store:</strong></p>
157
- <ul>
158
- <li>Your log content</li>
159
- <li>Sanitized output</li>
160
- <li>Custom patterns you create</li>
161
- </ul>
162
-
163
- <h2>6. Your Rights (GDPR & CCPA)</h2>
164
- <p>You have the right to:</p>
165
- <ul>
166
- <li><strong>Access:</strong> Request a copy of your data</li>
167
- <li><strong>Rectification:</strong> Correct inaccurate information</li>
168
- <li><strong>Erasure:</strong> Request account and data deletion</li>
169
- <li><strong>Data Portability:</strong> Download your data in portable format</li>
170
- <li><strong>Object:</strong> Object to data processing</li>
171
- <li><strong>Withdraw Consent:</strong> Opt-out of marketing emails anytime</li>
172
- </ul>
173
- <p>To exercise these rights, email: <strong><a href="mailto:hello@logshield.dev" style="color: inherit; text-decoration: none;">hello@logshield.dev</a></strong></p>
174
-
175
- <h2>7. Data Retention</h2>
176
- <ul>
177
- <li>Account data: Retained while account is active</li>
178
- <li>After deletion: Permanently removed within 30 days</li>
179
- <li>Backups: Deleted from backups within 90 days</li>
180
- <li>Legal requirements: Retained only if mandated by law</li>
181
- </ul>
182
-
183
- <h2>8. Cookies</h2>
184
- <p>We use minimal, essential cookies only:</p>
185
- <ul>
186
- <li><strong>Authentication cookie:</strong> Keeps you logged in (httpOnly, secure)</li>
187
- <li><strong>Preferences:</strong> Stored in localStorage (not transmitted to servers)</li>
188
- <li><strong>No tracking or advertising cookies</strong></li>
189
- </ul>
190
-
191
- <h2>9. International Data Transfers</h2>
192
- <p>LogShield operates globally. Your account data may be processed in:</p>
193
- <ul>
194
- <li>Indonesia (primary business location)</li>
195
- <li>Germany (development)</li>
196
- <li>United States (hosting via Vercel)</li>
197
- </ul>
198
- <p>We ensure adequate safeguards for international transfers per GDPR Article 46.</p>
199
-
200
- <h2>10. Children's Privacy</h2>
201
- <p>LogShield is not intended for users under 13 years of age. We do not knowingly collect information from children. If you believe we have collected data from a child, please contact us immediately for removal.</p>
202
-
203
- <h2>11. Changes to This Policy</h2>
204
- <p>We may update this Privacy Policy periodically. We will notify you of significant changes via email or prominent notice on the Service. Continued use after changes constitutes acceptance of the updated policy.</p>
205
-
206
- <h2>12. Contact Us</h2>
207
- <p>Questions or concerns about privacy?</p>
208
- <p><strong>Email:</strong> <a href="mailto:hello@logshield.dev" style="color: inherit;">hello@logshield.dev</a></p>
209
- <p><strong>Response time:</strong> Within 48 hours</p>
210
- <p><strong>Website:</strong> <a href="https://logshield.dev" style="color: inherit;">https://logshield.dev</a></p>
211
-
212
- <div style="margin-top: 40px; padding-top: 20px; border-top: 1px solid #e5e7eb;">
213
- <a href="/" class="back-button">Back to LogShield</a>
214
- </div>
215
- </div>
216
- </body>
217
- </html>
package/dist/refund.html DELETED
@@ -1,221 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Refund Policy - LogShield</title>
7
- <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
8
- <style>
9
- * { margin: 0; padding: 0; box-sizing: border-box; }
10
- body {
11
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
12
- line-height: 1.6;
13
- color: #333;
14
- background: linear-gradient(to bottom right, #f8fafc, #e0f2fe);
15
- min-height: 100vh;
16
- padding: 20px;
17
- }
18
- .container {
19
- max-width: 800px;
20
- margin: 0 auto;
21
- background: white;
22
- padding: 40px;
23
- border-radius: 12px;
24
- box-shadow: 0 4px 6px rgba(0,0,0,0.1);
25
- }
26
- .back-button {
27
- display: inline-flex;
28
- align-items: center;
29
- gap: 8px;
30
- padding: 10px 20px;
31
- background: #3b82f6;
32
- color: white;
33
- text-decoration: none;
34
- border-radius: 6px;
35
- font-size: 14px;
36
- font-weight: 500;
37
- transition: background 0.2s;
38
- margin-bottom: 30px;
39
- }
40
- .back-button:hover { background: #2563eb; }
41
- h1 { color: #1e40af; font-size: 32px; margin-bottom: 10px; }
42
- .last-updated { color: #6b7280; font-size: 14px; margin-bottom: 30px; }
43
- h2 { color: #3b82f6; font-size: 24px; margin: 30px 0 15px; }
44
- h3 { font-size: 18px; color: #1f2937; margin: 20px 0 10px; }
45
- p, li { margin-bottom: 15px; color: #4b5563; }
46
- ul, ol { margin-left: 30px; }
47
- strong { color: #1f2937; }
48
- .guarantee-box { background: #d1fae5; padding: 20px; border-left: 4px solid #10b981; margin: 20px 0; border-radius: 4px; }
49
- .entity-info { background: #f0f9ff; padding: 15px; border-left: 4px solid #3b82f6; margin: 20px 0; border-radius: 4px; }
50
- @media (max-width: 768px) {
51
- .container { padding: 20px; }
52
- h1 { font-size: 24px; }
53
- h2 { font-size: 20px; }
54
- }
55
- </style>
56
- </head>
57
- <body>
58
- <div class="container">
59
- <a href="/" class="back-button">
60
- <svg width="16" height="16" viewBox="0 0 16 16" fill="none">
61
- <path d="M10 12L6 8L10 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
62
- </svg>
63
- Back to LogShield
64
- </a>
65
-
66
- <h1>Refund Policy</h1>
67
- <p class="last-updated"><strong>Last updated:</strong> December 10, 2025</p>
68
-
69
- <!-- CRITICAL: Entity Information for Paddle -->
70
- <div class="entity-info">
71
- <strong>Refund Provider:</strong> This refund policy applies to all paid subscriptions for LogShield, a service operated by <strong>Hendra Afria</strong> ("LogShield", "we", "us", or "our").
72
- </div>
73
-
74
- <div class="guarantee-box">
75
- <h2 style="margin-top: 0; color: #065f46;">&#x1F49A; 14-Day Money-Back Guarantee</h2>
76
- <p style="margin-bottom: 0; color: #047857;">We're confident you'll love LogShield. If you're not satisfied for any reason, we offer a full refund within 14 days of purchase?no questions asked.</p>
77
- </div>
78
-
79
- <h2>1. Refund Eligibility</h2>
80
-
81
- <h3>&#x2705; Eligible for Full Refund:</h3>
82
- <ul>
83
- <li>Refund requests made within <strong>14 days</strong> of purchase</li>
84
- <li>First-time LogShield subscription (new customers)</li>
85
- <li>Technical issues preventing service use</li>
86
- <li>Service not functioning as described</li>
87
- <li>Accidental duplicate purchases</li>
88
- <li>General dissatisfaction with the service</li>
89
- </ul>
90
-
91
- <h3>&#x274C; Not Eligible for Refund:</h3>
92
- <ul>
93
- <li>Refund requests after <strong>14 days</strong> of purchase</li>
94
- <li>Violations of our Terms of Service</li>
95
- <li>Abusive or fraudulent use of the service</li>
96
- <li>Lifetime licenses after <strong>30 days</strong> of purchase</li>
97
- <li>Subscription renewal charges (must cancel before renewal date)</li>
98
- </ul>
99
-
100
- <h2>2. How to Request a Refund</h2>
101
- <p>To request a refund, please follow these steps:</p>
102
- <ol>
103
- <li><strong>Email us:</strong> <a href="mailto:hello@logshield.dev" style="color: inherit;">hello@logshield.dev</a></li>
104
- <li><strong>Subject line:</strong> "Refund Request - [Your Order Number]"</li>
105
- <li><strong>Include in your email:</strong>
106
- <ul style="margin-top: 10px;">
107
- <li>Order number or transaction ID</li>
108
- <li>Email address used for purchase</li>
109
- <li>Brief reason for refund (optional but appreciated)</li>
110
- </ul>
111
- </li>
112
- <li><strong>Our response:</strong> Within 24 hours</li>
113
- <li><strong>Refund processing:</strong> 5-7 business days after approval</li>
114
- </ol>
115
-
116
- <h2>3. Refund Processing Timeline</h2>
117
- <ul>
118
- <li><strong>Initial response:</strong> Within 24 hours of your request</li>
119
- <li><strong>Approval decision:</strong> Usually immediate (within 14-day window)</li>
120
- <li><strong>Refund processing:</strong> 5-7 business days</li>
121
- <li><strong>Credit to account:</strong> Refunded to original payment method</li>
122
- <li><strong>Bank processing:</strong> Additional 3-5 business days (varies by bank)</li>
123
- </ul>
124
-
125
- <h2>4. Subscription Cancellation</h2>
126
- <p>You can cancel your LogShield subscription at any time:</p>
127
- <ul>
128
- <li><strong>How to cancel:</strong> Account settings ? Subscription ? Cancel Subscription</li>
129
- <li><strong>Effect:</strong> No future charges will be made</li>
130
- <li><strong>Access:</strong> Service continues until end of current billing period</li>
131
- <li><strong>Data retention:</strong> Account data retained for 30 days, then permanently deleted</li>
132
- </ul>
133
- <p><strong>Important:</strong> Cancellation does not automatically trigger a refund. To receive a refund for your current billing period, you must request it within 14 days of purchase using the process above.</p>
134
-
135
- <h2>5. Special Cases</h2>
136
-
137
- <h3>Lifetime License</h3>
138
- <ul>
139
- <li><strong>Refund window:</strong> 30 days from purchase (extended from standard 14 days)</li>
140
- <li><strong>After 30 days:</strong> Non-refundable</li>
141
- <li><strong>Rationale:</strong> One-time purchases are final after the extended trial period</li>
142
- </ul>
143
-
144
- <h3>Team Plans</h3>
145
- <ul>
146
- <li>Same 14-day refund window applies</li>
147
- <li>Refund covers the entire team subscription</li>
148
- <li>All team members will lose access upon refund</li>
149
- </ul>
150
-
151
- <h3>Annual Subscriptions</h3>
152
- <ul>
153
- <li>14-day full refund from original purchase date</li>
154
- <li>After 14 days: No refund available, but can cancel to prevent next year's charge</li>
155
- </ul>
156
-
157
- <h3>Promotional Discounts</h3>
158
- <ul>
159
- <li>Refund amount: The actual amount you paid (after discount applied)</li>
160
- <li>Discount codes cannot be reused after refund is processed</li>
161
- </ul>
162
-
163
- <h2>6. Partial Refunds</h2>
164
- <p>We may offer partial refunds in exceptional circumstances:</p>
165
- <ul>
166
- <li>Extended service downtime (>24 consecutive hours)</li>
167
- <li>Critical feature unavailability affecting your use case</li>
168
- <li>Pro-rated refund for unused subscription time (evaluated case-by-case)</li>
169
- </ul>
170
- <p>Contact us at hello@logshield.dev to discuss partial refund eligibility.</p>
171
-
172
- <h2>7. Chargebacks</h2>
173
- <p><strong>Please contact us before filing a chargeback with your bank.</strong></p>
174
- <ul>
175
- <li>Chargebacks result in immediate account termination</li>
176
- <li>We're committed to resolving refund issues fairly and quickly</li>
177
- <li>Most refund requests are approved within hours during the eligible period</li>
178
- <li>Chargebacks incur additional processing fees we must pay to payment processors</li>
179
- </ul>
180
- <p>We value your satisfaction and will work with you to resolve any billing concerns.</p>
181
-
182
- <h2>8. Our Refund Commitment</h2>
183
- <p><strong>This is our core commitment to you:</strong></p>
184
- <p>We strive to make our refund process as transparent and straightforward as possible:</p>
185
- <ul>
186
- <li><strong>Transparency:</strong> Clear eligibility criteria and timelines</li>
187
- <li><strong>Fairness:</strong> Consistent application of policy to all customers</li>
188
- <li><strong>Communication:</strong> Regular updates throughout the refund process</li>
189
- <li><strong>Respect:</strong> Courteous treatment of all refund requests</li>
190
- </ul>
191
- <p>Our goal is your satisfaction. If LogShield isn't the right fit for your needs, we'll process your refund promptly and without unnecessary obstacles.</p>
192
-
193
- <h2>9. Policy Updates</h2>
194
- <p>We may update this Refund Policy periodically. We will notify you of significant changes via email or prominent notice on the Service. Continued use after changes constitutes acceptance of the updated policy.</p>
195
- <ul>
196
- <li>Minor updates: Posted on our website with updated "Last updated" date</li>
197
- <li>Major updates: Notified via email 30 days before changes take effect</li>
198
- <li>Existing customers: Refund requests are processed under the policy in effect at time of purchase</li>
199
- </ul>
200
-
201
- <h2>10. Governing Law</h2>
202
- <p>This Refund Policy is governed by and construed in accordance with the laws of <strong>Indonesia</strong>, without regard to its conflict of law principles. Any disputes arising from refund requests shall be subject to the exclusive jurisdiction of the courts located in <strong>Jakarta, Indonesia</strong>.</p>
203
- <p>For customers in the European Union, this policy is without prejudice to any mandatory statutory rights you may have under applicable consumer protection laws.</p>
204
-
205
- <h2>11. Contact Us</h2>
206
- <p>Questions or concerns about refunds?</p>
207
- <p><strong>Email:</strong> <a href="mailto:hello@logshield.dev" style="color: inherit;">hello@logshield.dev</a></p>
208
- <p><strong>Response time:</strong> Within 24 hours</p>
209
- <p><strong>Website:</strong> <a href="https://logshield.dev" style="color: inherit;">https://logshield.dev</a></p>
210
-
211
- <div style="margin-top: 40px; padding-top: 20px; border-top: 1px solid #e5e7eb;">
212
- <a href="/" class="back-button">
213
- <svg width="16" height="16" viewBox="0 0 16 16" fill="none">
214
- <path d="M10 12L6 8L10 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
215
- </svg>
216
- Back to LogShield
217
- </a>
218
- </div>
219
- </div>
220
- </body>
221
- </html>
package/dist/terms.html DELETED
@@ -1,140 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Terms of Service - LogShield</title>
7
- <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
8
- <style>
9
- * { margin: 0; padding: 0; box-sizing: border-box; }
10
- body {
11
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
12
- line-height: 1.6;
13
- color: #333;
14
- background: linear-gradient(to bottom right, #f8fafc, #e0f2fe);
15
- min-height: 100vh;
16
- padding: 20px;
17
- }
18
- .container {
19
- max-width: 800px;
20
- margin: 0 auto;
21
- background: white;
22
- padding: 40px;
23
- border-radius: 12px;
24
- box-shadow: 0 4px 6px rgba(0,0,0,0.1);
25
- }
26
- .back-button {
27
- display: inline-flex;
28
- align-items: center;
29
- gap: 8px;
30
- padding: 10px 20px;
31
- background: #3b82f6;
32
- color: white;
33
- text-decoration: none;
34
- border-radius: 6px;
35
- font-size: 14px;
36
- font-weight: 500;
37
- transition: background 0.2s;
38
- margin-bottom: 30px;
39
- }
40
- .back-button:hover { background: #2563eb; }
41
- h1 { color: #1e40af; font-size: 32px; margin-bottom: 10px; }
42
- .last-updated { color: #6b7280; font-size: 14px; margin-bottom: 30px; }
43
- h2 { color: #3b82f6; font-size: 24px; margin: 30px 0 15px; }
44
- p, li { margin-bottom: 15px; color: #4b5563; }
45
- ul { margin-left: 30px; }
46
- strong { color: #1f2937; }
47
- .entity-info { background: #f0f9ff; padding: 15px; border-left: 4px solid #3b82f6; margin: 20px 0; border-radius: 4px; }
48
- @media (max-width: 768px) {
49
- .container { padding: 20px; }
50
- h1 { font-size: 24px; }
51
- h2 { font-size: 20px; }
52
- }
53
- </style>
54
- </head>
55
- <body>
56
- <div class="container">
57
- <a href="/" class="back-button">
58
- <svg width="16" height="16" viewBox="0 0 16 16" fill="none">
59
- <path d="M10 12L6 8L10 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
60
- </svg>
61
- Back to LogShield
62
- </a>
63
-
64
- <h1>Terms of Service</h1>
65
- <p class="last-updated"><strong>Last updated:</strong> December 10, 2025</p>
66
-
67
- <!-- CRITICAL: Entity Information for Paddle -->
68
- <div class="entity-info">
69
- <strong>Service Provider:</strong> These Terms of Service govern your use of LogShield, a log sanitization service operated by <strong>Hendra Afria</strong> ("LogShield", "we", "us", or "our").
70
- </div>
71
-
72
- <h2>1. Agreement to Terms</h2>
73
- <p>By accessing and using LogShield ("the Service"), you agree to be bound by these Terms of Service. If you do not agree to these terms, please do not use the Service.</p>
74
-
75
- <h2>2. Service Description</h2>
76
- <p>LogShield provides a browser-based log sanitization service that removes sensitive data from text, including but not limited to API keys, tokens, credentials, personally identifiable information (PII), and other security patterns.</p>
77
-
78
- <h2>3. Use License</h2>
79
- <p>Subject to your compliance with these Terms, LogShield grants you a personal, non-exclusive, non-transferable, revocable license to use the Service for your personal or internal business purposes.</p>
80
-
81
- <h2>4. User Responsibilities</h2>
82
- <p>You agree to:</p>
83
- <ul>
84
- <li>Provide accurate account information</li>
85
- <li>Maintain the security of your account credentials</li>
86
- <li>Be responsible for all activities under your account</li>
87
- <li>Not use the Service for illegal purposes</li>
88
- <li>Not attempt to bypass usage limitations or restrictions</li>
89
- <li>Not reverse engineer, decompile, or attempt to extract source code</li>
90
- </ul>
91
-
92
- <h2>5. Payment Terms</h2>
93
- <p>Paid subscriptions are billed in advance on a monthly or annual basis through our payment processor (Paddle). All fees are in USD and are non-refundable except as described in our <a href="/refund.html" style="color: #3b82f6; text-decoration: underline;">Refund Policy</a>.</p>
94
-
95
- <p><strong>Subscription Plans:</strong></p>
96
- <ul>
97
- <li>Starter: $7/month</li>
98
- <li>Pro: $19/month</li>
99
- <li>Team: $79/month (5 seats)</li>
100
- <li>Lifetime: $199 one-time payment</li>
101
- </ul>
102
-
103
- <h2>6. Refund Policy</h2>
104
- <p>We offer a 14-day money-back guarantee for all new subscriptions. For complete details, please see our <a href="/refund.html" style="color: #3b82f6; text-decoration: underline;">Refund Policy</a>.</p>
105
-
106
- <h2>7. Privacy and Data Processing</h2>
107
- <p><strong>Important:</strong> LogShield processes all log data entirely client-side in your browser. We never see, store, or transmit your log content to our servers. For details on account data and analytics, see our <a href="/privacy.html" style="color: #3b82f6; text-decoration: underline;">Privacy Policy</a>.</p>
108
-
109
- <h2>8. Cancellation and Termination</h2>
110
- <p>You may cancel your subscription at any time through your account settings. Your access will continue until the end of your current billing period. We reserve the right to suspend or terminate accounts that violate these Terms.</p>
111
-
112
- <h2>9. Modifications to Service</h2>
113
- <p>We reserve the right to modify, suspend, or discontinue any part of the Service at any time with reasonable notice. We will not be liable for any modification, suspension, or discontinuance of the Service.</p>
114
-
115
- <h2>10. Intellectual Property</h2>
116
- <p>The Service, including its software, design, and content (excluding user-generated content), is owned by LogShield and protected by international copyright, trademark, and other intellectual property laws. The core sanitization patterns are available as open source under the MIT license.</p>
117
-
118
- <h2>11. Disclaimer of Warranties</h2>
119
- <p>THE SERVICE IS PROVIDED "AS IS" WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.</p>
120
-
121
- <h2>12. Limitation of Liability</h2>
122
- <p>IN NO EVENT SHALL LOGSHIELD BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES ARISING FROM YOUR USE OF OR INABILITY TO USE THE SERVICE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</p>
123
-
124
- <h2>13. Governing Law and Jurisdiction</h2>
125
- <p>These Terms are governed by and construed in accordance with the laws of Indonesia. Any disputes shall be resolved in the courts of Indonesia.</p>
126
-
127
- <h2>14. Changes to Terms</h2>
128
- <p>We may update these Terms from time to time. We will notify users of significant changes via email or through the Service. Your continued use after changes constitutes acceptance of the modified Terms.</p>
129
-
130
- <h2>15. Contact Information</h2>
131
- <p>For questions about these Terms of Service:</p>
132
- <p><strong>Email:</strong> <a href="mailto:hello@logshield.dev" style="color: inherit;">hello@logshield.dev</a></p>
133
- <p><strong>Website:</strong> <a href="https://logshield.dev" style="color: inherit;">https://logshield.dev</a></p>
134
-
135
- <div style="margin-top: 40px; padding-top: 20px; border-top: 1px solid #e5e7eb;">
136
- <a href="/" class="back-button">Back to LogShield</a>
137
- </div>
138
- </div>
139
- </body>
140
- </html>